SUPER gotcha

lachoy on 2002-08-21T14:09:06

Rule for the day: pay attention to the docs! I was wondering why SUPER wasn't working in generated classes/subs, illustrated by:

use strict;

package Foo;
sub save { return "saved!" }

package Bar;
@Bar::ISA = qw( 'Foo' );

package main;

sub create_sub {
    my ( $class, $method ) = @_;
    no strict 'refs';
    *{ $class . '::' . $method } = 
      sub {
          my ( $class ) = @_;
          return $class->SUPER::save();
      };
}

create_sub( 'Bar', 'save' );
print Foo->save(), "\n";
print Bar->save(), "\n";
Which prints:
>perl test_super.pl
saved!
Can't locate object method "save" via package "main" (perhaps you forgot to load "main"?) at test_super.pl line 21.

SUPER can only be used within the class, which makes me suspect that it's a compile-time directive. Or, as the docs (perlobj) state:

If you're trying to control where the method search begins and you're executing in the class itself, then you may use the SUPER pseudo class, which says to start looking in your base class's @ISA list without having to name it explicitly:
And one brief code example later there's another warning:
Please note that the SUPER:: construct is meaningful only within the class.
Oh well!


We've been 'round this loop before

pdcawley on 2002-08-21T15:57:40

Apparently Tk.pm relies on the current behaviour and would break if SUPER were made rather more runtime. Which is a royal pain in the arse and no mistake. Hence the HYPER idea that I proposed in p5p and, ISTR in one of my journal entries.

Yes, SUPER looks at @{__PACKAGE__."::ISA"}

merlyn on 2002-08-21T16:18:28

It's tied to __PACKAGE__, so it is in fact bound to package in which it was compiled. This means that this also fails:
package ThisPack;
sub ThatPack::a_method {
  ... $self->SUPER::blah(...);
}
because the SUPER will be relative to ThisPack's @ISA, not ThatPack's @ISA.