in reply to Re: Beginner's Object Orientation Exercises?
in thread Beginner's Object Orientation Exercises?

I made a Flashlight program.

#! 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)

Replies are listed 'Best First'.
(jeffa) 3Re: Beginner's Object Orientation Exercises?
by jeffa (Bishop) on Mar 18, 2002 at 04:11 UTC
    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.

Re: Re: Re: Beginner's Object Orientation Exercises?
by nop (Hermit) on Mar 18, 2002 at 03:04 UTC
    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.
Re: Re: Re: Beginner's Object Orientation Exercises?
by Juerd (Abbot) on Mar 18, 2002 at 06:50 UTC

    I made a Flashlight program.

    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) = @_; carp 'Please read the manual!' 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.


      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)