Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Re^2: Point me in the right direction with OO inheritance and static variables

by Amblikai (Scribe)
on Sep 02, 2014 at 11:41 UTC ( [id://1099253]=note: print w/replies, xml ) Need Help??


in reply to Re: Point me in the right direction with OO inheritance and static variables
in thread Point me in the right direction with OO inheritance and static variables

Wow! Thanks! This is pretty much exactly what i'm thinking of with some minor modification (i wish my program was about Unicorns called Twilight Sparkle!!

I'm having trouble following your subs "name", "colour" etc though.

Could you explain those? I'm guessing that if i attempt to get the value of "name" before i've assigned it a value, it'll call the _build_X sub and so return a default value. But i'm not entirely sure how it does it? Also i've never seen the "//=" operator before.

Thanks!

  • Comment on Re^2: Point me in the right direction with OO inheritance and static variables

Replies are listed 'Best First'.
Re^3: Point me in the right direction with OO inheritance and static variables
by tobyink (Canon) on Sep 02, 2014 at 12:03 UTC

    I've written them in quite a terse fashion. This is because when you're doing OO without any OO frameworks, you end up having to write a lot of these sort of little accessor subs, and making them as abbreviated as possible keeps you sane. Writing out the name sub in full might be:

    sub name { my $self = shift; if (not defined $self->{name}) { $self->{name} = $self->_build_name(); } return $self->{name}; }

    But if you're writing similar accessors for dozens of different attributes, it's nice to abbreviate them so they fit on a line each:

    sub name { $_[0]->{name} //= $_[0]->_build_name } sub colour { $_[0]->{colour} //= $_[0]->_build_colour } sub owner { $_[0]->{owner} } # this one has no default sub height { $_[0]->{height} //= 2.5 } # another way to provide a def +ault ...;

    Slight diversion...

    The disadvantage of the second way of doing defaults (shown above) is it makes the default harder to override when you create a subclass. If the height had been defaulted via $_[0]->_build_height then when we decided to write a Pony::Shetland class, we could simply override _build_height to return a different default value (maybe 1.2?). But with the default 2.5 hard-coded into the height sub itself, we need to override height in Pony::Shetland.

    Obviously, overriding the height sub in Pony::Shetland is perfectly possible. It's technically no more difficult than overriding _build_height. However, overriding _build_height rather than height seems preferable because OO code tends to be more maintainable when you're only overriding very small targeted bits of functionality.

    As an example, let's assume that Pony::Shetland overrides height from Horse. Now somebody goes and releases a new version of Horse with a brand new feature. It allows:

    my $aj = Horse->new(name => "Applejack"); my $metres = $aj->height( in => "metres" ); my $inches = $aj->height( in => "inches" ); my $hands = $aj->height( in => "hands" ); my $silly = $aj->height( in => "lightyears" );

    Nice piece of new functionality, eh? However, Pony::Shetland overrides height, so the new functionality doesn't work there! There's something called the Liskov substitution principle that says anything that works with the base class should work with subclasses. So we've broken that principle.

    If Pony::Shetland was just overriding _build_height, we would never have gotten ourselves into this quandary. The new height would still work in Pony::Shetland.

    End of slight diversion!

    Regarding //=... the // and //= operators were introduced in Perl 5.10. // is much the same as || but rather than testing the truthiness of the left hand value, it tests the definedness. The number 0 and the empty string are defined but false, so if you wanted to be able to have horses with a name "0", this distinction could be important.

    $foo //= $bar is shorthand for $foo = ($foo // $bar), so it means the same as if (not defined $foo) { $foo = $bar }.

      Thanks again, it all makes sense now!

      I've since found that i have another problem though. I was running with an older version of perl(5.8.8) and it didn't like some of the code. I've since upgraded locally to 5.20 and i've had to recompile my local modules but i think i have it working now.

      The problem that i'm having is that my script can't find the parent class file.

      In my main script i have the following:

      use ChildObjects; use ParentObjects;

      I then have the 2 files: ChildObjects.pm and ParentObjects.pm

      Inside the ParentObjects.pm file i have:

      package ParentObjects;

      Inside the ChildObjects.pm file i have:

      package ChildObjects; use parent -norequire, "ParentObjects";

      When i then try in my script:  my $obj=ChildObjects->new(); But i get the following error from my script: Can't locate package ParentObjects for @ChildObjects::ISA at ./script.pl line 54

      Can you help? Am i naming/calling my package files wrong?

        I perhaps should have pointed out that in general, you don't want to use parent's -norequire option.

        -norequire is a hint to parent that it shouldn't try to load the file which the base class lives in. In my example, both classes were in the same file, so trying to load a separate file for the base class would not lead to success. Once you've split the parent into its own file, you should do something like:

        use parent "ParentClass";
        If you have your parent and child classes in separate files then you need to get rid of the '-norequire' switch:
        package ChildObjects; use parent qw(ParentObjects);
        See the docs for parent

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1099253]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (5)
As of 2024-04-19 05:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found