in reply to Inheritance automation help

I got a little further with this, and feel a little better about it. I think what it comes down to is that I was trying to do something that inheritance isn't able to accomplish innately - and for some reason I thought I could wiggle it around to get it to work. Here is another concept I was working on to accomplish the above goal:
use Top; my $test = new Top (Foo=>'Start Foo'); use Top::Extend1; $test = plugin Top::Extend1 ($test, %settingsScopedToExtend1); use Top::Extend2; $test = plugin Top::Extend2 ($test, %settingsScopedToExtend2);
The passing of test to each one holds the class, it gets mashed together, altered slightly depending on what the Extend class is doing and passed back to $test with extra methods attached and altered class variables. The end result is that I needed to append classes to each other. So at any time I can call my base class and have new methods that were not there before, but were added because of calling its constructor named plugin that does a "cloneish" concept. Feel free to let me know if I'm off my rocker on doing something like this! Or there is a GOTCHA that I'm not thinking of that isn't obvious like accidental overwriting of methods and such. Also here is an example of what the Extend1 plugin constructor would look like in the Extend1 Package:
sub plugin { my ($class, $other, %params) = @_; # # bless my new combined class # $other = bless $other, $class; # # set defaults scoped to Extend1 # $other->{"Extend1"}->{"someSetting"} = 'its value'; # # overwrite defaults # @{$other->{"Extend1"}}{keys %params} = values %params; # # update any $other data # $other->{'Foo'} .= ' Appended to it '; # # pass back our extended class # return $other; }

Replies are listed 'Best First'.
Re^2: Inheritance automation help
by GrandFather (Saint) on Apr 05, 2012 at 21:16 UTC

    You still haven't told us what you are trying to achieve, but it looks like you are setting up a test suite with pluggable tests. I'd structure it somewhat differently by having a test harness class (your Top class) and pluggable classes (your ExtendX classes). You may want a pluggable base class that knows how to hook itself up to the test harness, but most likely you'd do that by creating pluggable class instances and registering them with the harness. Something like this:

    #!/usr/bin/perl use strict; use warnings; package Harness; sub new { my ($class, %params) = @_; my $self = bless \%params, $class; return $self; } sub register { my ($self, $plugin) = @_; push @{$self->{plugins}}, $plugin; } sub run { my ($self) = @_; my @results; for my $test (@{$self->{plugins}}) { print "Running ", $test->name(), "\n"; push @results, $test->run($self); } print "$_\n" for @results; } package PluginBase; sub new { my ($class, %params) = @_; my $self = bless \%params, $class; return $self; } sub name { my ($self) = @_; return ref $self; } sub run { my ($self) = @_; return "Skipped " . $self->name() . " test - no run override provi +ded"; } package WinkTest; push @WinkTest::ISA, 'PluginBase'; sub run { my ($self) = @_; my $type = ref $self; return "Wink, wink. Wink test passed OK"; } package BlinkTest; push @BlinkTest::ISA, 'PluginBase'; package main; my $test = Harness->new(); $test->register (WinkTest->new()); $test->register (BlinkTest->new()); $test->run();

    Prints:

    Running WinkTest Running BlinkTest Wink, wink. Wink test passed OK Skipped BlinkTest test - no run override provided

    Please note the PackageName->constructor() style used to invoke package methods. The old constructor PackageName() style is pretty much deprecated because it is prone to parsing difficulties.

    True laziness is hard work
      I just finished up cleaning up the mess I created. The end result was a combination of using test case registering, and because of the structure and portability of what I'm working with I had to add @ISA for what I was calling the "parent" inside what I was calling the "child". My end result of this discussion took me A LOT further than I ever thought I was going to get with it! This isn't something I would ever do as design, but here is an example in concept of what I did:
      #!/usr/bin/perl use strict; use warnings; package Top; sub new { my ($class, %params) = @_; my $self = bless \%params, $class; return $self; } sub firstSub { my ($class) = @_; print "FIRST SUB!\n"; } package Top::Extend1; push @Top::ISA, 'Top::Extend1'; sub addOnSub { my ($self) = @_; print "ADD ON\n"; } package Top::Extend2; push @Top::ISA, 'Top::Extend2'; sub secondAddOn { my ($self) = @_; print "SECOND ADD ON\n"; } package main; my $test = Top->new(); $test->firstSub(); $test->addOnSub(); $test->secondAddOn();
      So the way I was saying it was backwards making my question confusing to what my actual goal was. I'm sure this is very "hand slapish" behavior and complicated when it comes to overridden methods... but that was the key to solving my dilemma. Thanks for the help and enlightenment Monks!

        You might be better off with something like Moose::Role instead of this. Fiddling with someone else's @ISA is a good way to make a mess of fragile code.


        Improve your skills with Modern Perl: the free book.

      Thanks for the great post GrandFather. Sorry, I didn't mean to avoid describing correctly what I'm attempting to achieve. It was more of the matter of not knowing the right question to ask and the way to say it. I'm working on a internal content creation project that needs plug-able modules that add extra methods and change class variables, without ever knowing that it happened. The end result would be executing code that creates dynamic content against the new class that had the modules plugged into it that would use the new methods, and use the newly changed class variables. I just got back from traveling so I'm back to my project to get some more progress on it. I'll post my new result once I'm completed so you can see your wisdom induced idea. I truly appreciate your help and have learned a great deal from your posts, I think your last test suite idea will be ideal for what I'm trying to achieve!