http://qs321.pair.com?node_id=152362

in reply to Beginner's Object Orientation Exercises?

Does anyone have any ideas for excercises I could try that use OO?

Try creating virtual versions of machines that exist in real. You could create a slot machine (has to know how much the user has won, has to count statistics, has to know how many credits are left, should accept money, should pay out) or the money mechanics in a coffee machine (how much money is there left? how can that be divided into coins?) or a "simple" flashlight (must have on/off, must know whether it's on or off, must know how much battery power is left, must be able to tell how bright the light is at the current power level, and could have a flash button).

I've only read the Perlboot manpage, and have no other knowledge of Object Orientation

Thanks, I hope someone can come up with something!

Don't forget that using object oriented modules can help a lot. Try to know _why_ they are object oriented instead of functional, try to figure out how the objects work, and read sources.

Good luck!!

```U28geW91IGNhbiBhbGwgcm90MTMgY
W5kIHBhY2soKS4gQnV0IGRvIHlvdS
ByZWNvZ25pc2UgQmFzZTY0IHdoZW4
geW91IHNlZSBpdD8gIC0tIEp1ZXJk
```

• Comment on Re: Beginner's Object Orientation Exercises?

Replies are listed 'Best First'.
Re: Re: Beginner's Object Orientation Exercises?
by munchie (Monk) on Mar 18, 2002 at 01:54 UTC

```#! Perl
use vars qw(\$on \$pwrlvl);
use strict;

my \$on = "no";
my \$pwrlvl = "3";
my \$fl = "Flashlight";

print "You are holding a flashlight. What will you do? \n";
print "(TurnOn, TurnOff, Flash, ChangePowerLevel, ExitProgram)\n";
print "/Status Checks/=\\ pwrlvl, ison \\\n";

while(<STDIN>) {
chomp;
if (/^Change/) {
print "Enter Level: ";
chomp (my \$lvl=<STDIN>);
print \$fl->ChangePowerLevel("\$lvl");
print "\n";
} elsif (/^(exit|q|end|x|quit)/i) {
exit;
} else {
print \$fl->\$_ ."\n";
}
}

{ #1
package Flashlight;

sub TurnOn {
\$on = "yes";
return "The light is on.";
}
sub TurnOff {
\$on = "no";
return "Light is now off.";
}
sub Flash {
if (\$on eq "no") {
return "A flash of light beams through the air!";
} else {
return "The flashlight is on already.";
}
}
sub ChangePowerLevel {
my \$class = shift;
my \$level = shift;
\$pwrlvl = \$level;
return "The Power level is set at \$pwrlvl";
}
sub pwrlvl {
return "Power is at \$pwrlvl";
}
sub ison {
return "Is it on? Well, \$on";
}
}
It has everything but the battery power, which will be easy to implement in a few minutes when I find time.

Commands: ison, pwrlvl, ChangePowerLevel, TurnOn, TurnOff, Flash

> munchie, the number munchin newb
Llama: The other other white meat!
(you had to be there :-P)

Hmmmm, nop is right ... that is not really OO. You are using packages alright, but not in an OO manner. First, you need a constructor to create the object:
```package Flashlight;

sub new {
my \$class = shift;
my \$power = shift || 0;
my \$level = shift || 0;

my \$self  = {
level => \$level,
power => \$power,
};

return bless \$self, \$class;
}
This allows you to set a level and whether it is on or off when you instantiate (create) the object:
```my \$light = Flashlight->new(1,4);
which will create a flashlight that is on(1) with a level of 4.

Next, you really shouldn't print messages to STDOUT inside an object's method(s). Instead, methods really should generally only get and set values. This means that your methods Flash and ChangePowerLevel really belong in the client that uses your Flashlight object. Also, pwrlvl and ison should return true or false values, and should be renamed to more standard names like change_level and is_on.

Here is a complete re-write of your good but flawed first attempt (don't fret it, OO is an art form that takes a looong time to 'get'). Like music, this is just my interpretation of the problem at hand.

Errrr..... there's no OO in your example. There's no object. No blessed reference. You hold state in globals -- yack! Perhaps give a closer read to perlboot, perltoot, perltootc, perlobj,and perlbot. When done properly, the same code should support more than one flashlight -- with no conflicts between them.
nop

A program? I thought you wanted to exercise OO? Object properties are usually stored in the object itself, so that you can create multiple instances. If in your program you find that you need another flash light, you'll have to duplicate your entire package, or at least modify it heavily, to support multiple on/off states.

I took the liberty of re-writing it, so you can OO the other machines yourself.

```package Flashlight;
use Carp;
use Time::HiRes qw/usleep/;
use strict;

sub new {
my (\$class, %options) = @_;
my \$self = { };
my @required = qw/color/;
my @optional = qw/batteries_included type battery_type/;
for (@required) {
croak "Required named argument \$_ was not defined"
if not defined \$options{\$_};
\$self->{\$_} = \$options{\$_};
}
for (@optional) {
\$self->{\$_} = \$options{\$_} if exists \$options{\$_};
}
return bless \$self, \$class;
}

sub color {
my (\$self) = @_;
return lc \$self->{color};
}

sub charge_batteries {
my (\$self, \$type) = @_;
if defined \$type and \$type ne \$self->{battery_type};
return \$self->{batteries_included} = 1;
}

sub is_on {
my (\$self) = @_;
return \$self->{on};
}

sub is_off {
my (\$self) = @_;
return ! \$self->{off};
}

sub on {
my (\$self) = @_;
return undef if not \$self->{batteries_included};
\$self->{on} = 1;
return return 1;
}

sub off {
my (\$self) = @_;
return \$self->{on} = 0;
}

sub switch {
my (\$self) = @_;
return undef if \$self->is_off and not \$self->{batteries_included};
return \$self->{on} = ! \$self->{on}
}

sub flash {
my (\$self, \$duration) = @_;
croak 'Cannot flash while on' if \$self->is_on;
croak 'Cannot flash for a negative number of seconds' if \$duration
+ < 0;
carp 'flash() should be used to do nothing at all, changing durati
+on'
if defined \$duration and \$duration == 0;
\$duration ||= 0.1;
\$self->on();
usleep \$duration;
\$self->off();
}

All those \$self's and the new constructor indicate this flashlight is an object, and you can create as many flashlights as you want.

Now, it's your turn. I can say only one thing: try harder.

```U28geW91IGNhbiBhbGwgcm90MTMgY
W5kIHBhY2soKS4gQnV0IGRvIHlvdS
ByZWNvZ25pc2UgQmFzZTY0IHdoZW4
geW91IHNlZSBpdD8gIC0tIEp1ZXJk
```

I think I'm understanding better now. I read boot over again, and I payed more attention this time. I'm working on an exercise now, which will hopefully be better than the last.

> munchie, the number munchin newb
Llama: The other other white meat!
(you had to be there :-P)