in reply to Extending objects

Instead of a random directory structure, I prefer to create a proper module:

h2xs -AXc -n FooBar

...which will create a FooBar directory that contains the following:

Changes MANIFEST Makefile.PL README lib- |-- Foobar.pm t/

Then, create a FooBar directory within the lib dir, and put your Bar.pm and Foo.pm in that. I use the FooBar.pm as a module that contains any methods that will be common to more than a single sub class. So, in Foo.pm and Bar.pm, I'd have:

use base qw( FooBar );

In FooBar, some of the common subs I'd have are a generic new(), database setup subs, configuration file setup subs etc. Then, unless Foo or Bar require specific, non-generic versions of these subs, they will automatically be inherited when use()ing FooBar::Bar and FooBar::Foo without having to recreate the subs in each module file.

All in all, with the directory structure above and with this setup you could have:

# lib/FooBar.pm package FooBar; sub new { my $class = shift; my $args = shift; my $self = bless { name => $args->{ name }, age => $args->{ age }, }, $class; } return $self; } # lib/FooBar/Foo.pm package FooBar::Foo; use base qw( FooBar ); # no new() sub, it's inhereted sub age { my $self = shift; my $args = shift; $self->{ age } = $args->{ age } if $args->{ age }; return $self->{ age }; } # lib/FooBar/Bar.pm package FooBar::Bar; use base qw( FooBar ); # no new again sub name { my $self = shift; my $args = shift; $self->{ name } = $args->{ name } if $args->{ name }; return $self->{ name }; } # foo.pl use FooBar::Foo; use FooBar::Bar; # don't need to 'use' FooBar here my $foo = FooBar::Foo->new({ name => 'stevieb', age => '35', }; my $current_age = $foo->age(); my $year_older = $foo->age({ age => 36, });

Because you have a proper module setup, simply:

perl Makefile.PL sudo make install

to begin using your modules system-wide

I hope this helps in some way

Steve

Replies are listed 'Best First'.
Re^2: Extending objects
by JavaFan (Canon) on Jul 07, 2010 at 15:19 UTC
    That's just plain weird. Now you have a parent class that has knowledge how it's subclasses are implemented (as it's the parent class that is storing the attributes the subclasses use). You're going out of your way to break encapsulation.

    And how it's going to work anyway? Your $foo is of class FooBar::Foo, which has FooBar in its inheritance tree (that is, assuming you would actually have package statements, which you don't). But then you call the method age, which is defined in FooBar::Bar, which is not inherited by FooBar::Foo.

Re^2: Extending objects
by punkish (Priest) on Jul 07, 2010 at 15:29 UTC
    Thanks! This is brilliant. I didn't know about h2xs -AXc -n, so that itself is a great tip. The only issue I have with your approach is that Foo and Bar are inherited from Foobar, which works against the mental model I had of this. In my mental model, Foobar was inherited from Foo as well as from Bar. As JavaFan termed it, it was multiple inheritance I was after. Your approach requires in foo.pl

    use FooBar::Foo.pm use FooBar::Bar.pm

    I want the user to be shielded from the inner workings of Foobar. So, as far as the user is concerned, only the following should be required in foo.pl

    use Foobar;

    That way I can add more "parents" to Foobar in the future, if required. For example, I could modify Foobar to inherit from Baz.pm as well, but the user would not have to change foo.pl.

    All that said, many thanks for your very clear explanation.

    --

    when small people start casting long shadows, it is time to go to bed

      The example I used wasn't a good one ;) It is upside-down in the traditional sense, and based on a project I have that contains numerous modules that require a centralized configuration mechanism so I can use each module individually, as opposed to having to load them all via the parent each and every time.

      Pointers to a better way for this very welcome.

      Cheers,

      Steve