http://www.perlmonks.org?node_id=187591

DigitalKitty has asked for the wisdom of the Perl Monks concerning the following question:

Hi all.

In my never-ending quest for perl knowledge, I am teaching myself how to work with objects, classes, packages, etc. The following code is my first such script. I would be most appreciative if you could make some helpful comments / criticisms / etc. regarding how I might improve this fragile foundation.
Thanks,
-Katie.
#!/usr/bin/perl -w #class file. package Food; use strict; sub new { my $meal = { beverage => "Pepsi", entree => "soup", dessert => "ice cream", }; bless( $meal ); return $meal; } sub dessert { my $self = shift(); $self->{ dessert } = shift() if ( @_ ); return $self->{ dessert }; } sub entree { my $self = shift(); $self->{ entree } = shift() if ( @_ ); return $self->{ entree }; } sub beverage { my $self = shift(); $self->{ beverage } = shift() if ( @_ ); return $self->{ beverage }; } sub setMeal { if ( @_ == 4 ) { my $self = shift(); $self->dessert( $_[ 0 ] ); $self->entree( $_[ 1 ] ); $self->beverage( $_[ 2 ] ); } else { print( "Method setMeal requires additional args.\n" ); } } sub display { my $self = shift(); print( $self->dessert ); print( ", " ); print( $self->entree ); print( ", and " ); print( $self->beverage ); } 1;

#!/usr/bin/perl -w use Food; use strict; my $meal = new Food; $meal->setMeal( "iced tea", "salad", "cheesecake" ); print "I would like "; $meal->display(); print " please."; print( "\n" );


In addition, if you know of a good OOP book for perl ( aside from the excellent Conway text ), could you post it? My former college professor ( Jerry ), a few other students and I are going to start work on a major perl project this Fall. He hasn't provided us with any other details but I'm already looking forward to it.

Edit kudra, 2002-08-05 Added a READMORE tag

Replies are listed 'Best First'.
Re: Object Oriented Programming in Perl.
by fuzzyping (Chaplain) on Aug 05, 2002 at 06:12 UTC
    The only thing that really sticks out like a sore thumb is that you've disregarded the class name which is passed to your constructor. Beyond that, if you're going to just use the package to create a hashref, you might as well do it via the constructor as well, with alternative defaults. Your first sub could/should/might (TMTOWTDI) look something like this:
    sub new { my ($class, $args) = @_; bless { beverage => $args->{beverage} || "Pepsi", entree => $args->{entree} || "soup", dessert => $args->{dessert} || "ice cream", }, $class; }
    At this point, it's simple to add another method to get/set/modify your object's individual attributes, or as a whole. You asked for alternative resources on OOP. Honestly, I can't think of anything more rewarding than Chapter 3 of Damian's book. If you haven't sat down and read it in it's entirety, you're performing a disservice to yourself. Quite honestly, it is the bible... I had numerous lightbulbs "go off" before I was done with this chapter. :)

    -fp

    Update: Fixed the constructor. Thanks to Zaxo for catching the error.
Re: Object Oriented Programming in Perl.
by frankus (Priest) on Aug 05, 2002 at 09:10 UTC
    Hi, A few things I use that, of course, are optional (after all this is Perl)
    • Use the package name in the 'bless' statement : bless $self, $package;. Then call it using my $meal = Food->new()
    • Consider permitting the setting of parameters in the new method, perhaps by using a statement like this:
      my ($package,$params) = @_; my $self = ( ref($params) eq 'HASH' ) ? $params : {};
    • Factor in the use of namespaces, incase anyone decides your object is worth inheriting from.

    As an aside, just Perl foibles of mine:

    • in the display function, why use all those print functions when one could be used?
    • use double-quoted variables only when you have to. Use single quotes unless you are interpolating variables in the string.

    I mention the foibles as they're are inneficiencies so easily avoided.
    Using OO Perl is going to slap an overhead on your code, make sure the code is lean.

    As for OO Perl books apart from Damien Conway's OO Perl.. sure there are;
    however the Conway book is IMHO well worth reading instead of citing, get it from a library if you can't afford it.
    If you find the reading tricky, that's because the topic is tricky.
    If you wish to understand OO Perl conventions, better to read this book. In the mean time try:

    --

    Brother Frankus.

    ¤

Re: Object Oriented Programming in Perl.
by Basilides (Friar) on Aug 05, 2002 at 09:30 UTC
    Well, one piece of advice for OO in Perl which I myself picked up from this site (in dws's comments here), is that it's a tidy piece of good practice to separate your blessing from actually initialising your object variables. This requires 2 methods, which you might as well call sub new and sub initialise.

    So for your constructor, you'd have:

    package Food; sub new { my $class = shift; my $self = bless {}, $class; $self->initialize; $self; } sub initialize { my $self = shift; $self->{_beverage} = "Pepsi"; $self->{_entree} = "soup"; $self->{_dessert} = "ice cream"; }
    I think it's conventional to put an underscore before your object variable names too, eg _beverage.

    This may look like a bit of a waste of space, but its neatness might become a bit more obvious when you are actually passing initialisation info to the constructor (as opposed to everything starting off as Pepsi, soup, ice cream). Then you'd change the line in new to $self->initialize(@_);, and then have

    sub initialize { my $self = shift; $self->{_beverage} = shift; $self->{_entree} = shift; $self->{_dessert} = shift; }
    Call it with something like
    my $meal = new Food("tea", "sushi", "creme egg");
    HTH
    Dennis
      I think it's conventional to put an underscore before your object variable names too, eg _beverage.

      Erm, that's only for private properties, the rest are not prefixed with an underbar.
      From perltoot:

      Occasionally you'll see method names beginning or ending with an underscore or two. This marking is a convention indicating that the methods are private to that class alone and sometimes to its closest acquaintances, its immediate subclasses. But this distinction is not enforced by Perl itself. It's up to the programmer to behave.

      I feel your statement is misleading. New developers could use underbar incorrectly in their own code, and using other folks modules.

      --

      Brother Frankus.

      ¤

Re: Object Oriented Programming in Perl.
by fruiture (Curate) on Aug 05, 2002 at 11:24 UTC

    just in addition to the others' constructors:

    sub new { my $class = shift; $class = ref $class || $class; # other stuff bless $self,$class; }

    It allows you to use the constructor as an instance method. This is also described in perltoot and imho very usefull.

    --
    http://fruiture.de

      just to give you all the info, there are some people who do not think that the

      my $class = shift; $class = ref $class || $class;
      construction is useful or appropriate in a constructor. I'm just getting into this OOP stuff myself, and have avoided that particular method mostly because of posts by tilly and merlyn. Tilly uses some examples you might like in A Cat's eye view of OO (though all of the thread might be helpful) and even refers to merlyn's take on the matter, ref($proto) - just say no!. and of course, there are excellent resources in the tutorials section, specifically the Perl Object Oriented Meta-Tutorial , which is basically a list of further resources.

      good luck with the OOP in perl, from someone who's also in the middle of struggling with it!
      --au