in reply to maintaining constructor inheritance cascade

I'm a little confused. Why aren't you just doing:
package myParent; our @ISA; sub new { my $class = shift; bless $self,$class; $self->_init(@_); return $self; } sub _init { my $self = shift; print "_initParent (@_)\n"; } #---------------------------------- package myChild; our @ISA; use base qw(myParent); # This function is completely unnecessary #sub new { # my $class = shift; # my $self = $class->SUPER::new; # $self->_init(@_); # return $self; #} sub _init { my $self = shift; print "_initChild (@_)\n"; }
Or, am I missing something?

------
We are the carpenters and bricklayers of the Information Age.

Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

Replies are listed 'Best First'.
Re: Re: maintaining constructor inheritance cascade
by jaa (Friar) on May 14, 2003 at 14:35 UTC
    The _initXXX() subs are all private subs that need to ALL be called in a cascade when an instance is created. This is the output from my example:
    _initParent a b c [ISA: ] _initChild a b c [ISA: myParent] _initGrandChild a b c [ISA: myChild]
    And this is the output from your mod:
    _initChild (a b c) _initGrandChild a b c [ISA: myChild]
    The myParent->_init() code never got executed. Yes, you could call $self->SUPER::_init(@_) in your myChild->_init(), but that is missing the point.

    The _initXXX() methods are private to the respective classes - they are not part of the external interface, and are not intended to be specialised by a child class.

    Hope that makes sense?

      Ok. I get the picture now. (Sounds like a goofy design to me, but whatever.)
      package myParent; our @ISA; sub new { my $class = shift; bless $self,$class; $self->_parent_init(@_); return $self; } sub _parent_init { my $self = shift; print "_initParent (@_)\n"; } #---------------------------------- package myChild; our @ISA; use base qw(myParent); sub new { my $class = shift; my $self = $class->SUPER::new; $self->_child_init(@_); return $self; } sub _child_init { my $self = shift; print "_initChild (@_)\n"; }
      Etc. The idea is that your constructor is a wrapper on your parent's constructor, but you do additional things after that's called. So, the delta off your original code is that there is only one bless - in the ultimate parent's code. (You were doing a bunch of reblessing, which I think was confusing you.)

      ------
      We are the carpenters and bricklayers of the Information Age.

      Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

      Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

        Note that the poster asked about multiple inheritance. To handle that use TheDamian's module NEXT and then call NEXT instead of SUPER.

        Unfortunately that does have to be done in all modules in the inheritance tree. If this is not acceptable, the asker will likely have to examine all of the classes @ISAs to find all of the init methods and then call them all in turn.

        Excellent, it is an improvement - so I end up with proper cascading constructors using:
        sub new { my $class = shift; my $self = $class->SUPER::new(@_); $self->_initChild(@_); return $self; }

        Which is cleaner than looking at @ISA for a possible parent.

        Thanks!