|Don't ask to ask, just ask|
Not quite an OO tutorialby GrandFather (Sage)
|on Feb 23, 2011 at 10:21 UTC||Need Help??|
I put the following code sample on my scratch pad to encourage Lady_Aleena to investigate object oriented Perl. To my surprise it seems to be working (LA took notice ;) ). To my further surprise others have noticed and seem to like it so I captured the code here to give it a little more permanence and to provide a better forum for discussion than the CB.
I've split the code into a module and a script (although the original sample had all the code in the script) as a sop toward the convention of placing library code in modules. First the module code (placed in a file named RandomThings.pm):
and the sample script:
which when run prints stuff like:
First off, try to ignore the overload stuff (use overload and _asStr) which is really there as a cute way to avoid a bunch of method calls and concatenation operators when composing strings (and if that doesn't make sense yet just let your eyes glaze over and ignore it).
Ok, so look at the code between package RandThing and package RandDayPart. That is the code for the RandThing base class. sub new is the 'constructor'. It is used to create a RandThing (or derived class) 'object'. You can see how it is used in the my $tense = RandThing->new ('was', 'is', 'will be'); line in the sample script. The magic is in the bless which takes a reference (in this case a hash reference) and ties it to a variable using some magic string.
The magic kicks in when you 'call a member function' using code like $self->genValue ();. The blessed magic finds the genValue sub in the RandThing package and calls it passing $self as the first parameter. Notice that genValue creates a local variable $self and set it to the first parameter passed to the sub. We can now use $self in the sub to access the data referenced in the bless that created the object (look a sub genValue to see what I mean).
Ok, so far so good, but a lot of work for no apparent gain eh (still ignoring the overload stuff remember)?
In this example the good stuff becomes evident when we need to add a few different types of random thing. Really what we want is to have a few RandThingXXX types which provide their own lists of values. There are of course many ways to achieve that of course and, as with most fairly trivial examples, this probably isn't the best way. However ...
Take a look at the code following package RandDayPart. Note that there are a number of rather similar looking blocks, each prefixed by a package line. Note too that each block has a use parent line and a new sub, but nothing else.
The use parent makes the current package a 'sub-class' of the parent ('base') class. That means that if the bless magic can't find a 'member function' in the current package it will look in the parent package (and so on up if required). This stuff is 'inheritance' and is what lets us write all those packages that just have a constructor in them, but which still do useful stuff. Most of the real work gets done in the base class.
Note that the derived class constructors (new subs in RandDayPart etc.) use SUPER to call new in the parent package. The actual object is created in RandThing using values passed in by the derived class constructors.
Now, that's probably not anywhere near enough explaination yet, but I'm going to let the dust settle a little at this point and see who has questions or comments.
True laziness is hard work