in reply to Weird inheritance and SUPER

You must be missing something here because Q::bar() attempts to call a superclass method's bar() but Q does not have any superclass. When you take Q::bar() out of the picture, perl goes to the next superclass of QPrime which is Pprime and follows its superclasses and finds P::bar() which behaves properly. If you declare a superclass for Q that contains a bar() method or remove the $self->SUPER::bar() from the existing Q::bar(), you should be OK.

--- print map { my ($m)=1<<hex($_)&11?' ':''; $m.=substr('AHJPacehklnorstu',hex($_),1) } split //,'2fde0abe76c36c914586c';

Replies are listed 'Best First'.
Re: Re: Weird inheritance and SUPER
by roundboy (Sexton) on Jan 22, 2003 at 02:41 UTC

    Thanks, yes, the change you suggest do eliminate the error. But:

    • I specifically cannot add a superclass, because I'm not allowed to change the class hierarchy; and
    • Calling P::bar is really the goal of the exercise, because every instance of Q ever created will actually come from a subclass that also inherits from P.

    My problem, upon reflection, was that in trying to understand this, I read the following in my trusty Camel:

    SUPER...follows @ISA just as the regular inheritance mechanism does: in left-to-right, recursive, depth-first order. (3e, p. 325)

    However, I'd failed to read notice the following:

    A SUPER method consults the @ISA only of the package into which the call to SUPER was compiled. It does not care about the class of the invocant, nor about the package of the subroutine that was called. (ibid)

    I guess I expected that SUPER would follow the invocant's class hierarchy.

    As I mentioned in my original post, I solved the problem by renaming Q::bar, but now I'm curious. Is there a way to get the behavior I was looking for, without either changing method names or the class hierarchy? I imagine this would be some magic to replace the SUPER

    Thanks.
    --roundboy

      Is there a way to get the behavior I was looking for, without either changing method names or the class hierarchy?

      No.

      The method call, Qprime::bar has been resolved already. Now another method call, Q::SUPER::bar, needs to be resolved.

      You are using the wrong tool. If you got what you say you want you would have a loop repeatedly calling Q::bar.

      Usually SUPER is used to add functionality to a method:

      sub Child::foo { SUPER::foo; # do parent functionality blah; # add child functionality }
      Changing the order of the @Qprime::ISA elements might be a possible solution.

      If the hierarchy is carved in stone, i.e. you can't even change an @ISA, then you might make explicit calls: $self->P::bar.

      Maybe Q needs to also inherit from P? You can't make assumptions about peer classes. If Q is related to P, then this should be stated in Q's @ISA. If this is not satisfactory, then maybe Q needs to delegate to P in which case the relationship is by composition but this would require some changes to your class hierarchy.

      --- print map { my ($m)=1<<hex($_)&11?' ':''; $m.=substr('AHJPacehklnorstu',hex($_),1) } split //,'2fde0abe76c36c914586c';

      So you want:

      P: foo Q: bar P: bar
      right?

      Look into the NEXT module. It does exactly what you need: it follows @ISA along all the run-time class inheritance tree

      -- 
              dakkar - Mobilis in mobile
      

        Ah, this is exactly what I was looking for. Thanks! I apologize for not acknowledging this sooner - I got pulled into a project that left me zero time to look here.

        I suppose I should have figured there was a Damian to do it.

        --roundboy