in reply to Re: can('SUPER::defaults')
in thread can('SUPER::defaults')

The weird thing, however, is that the result of using SUPER depends on the package where you use it and not on the object instance. I modified chromatic's code to demonstrate this:

use strict; package A; sub new { my $pkg = shift; bless {}, $pkg; } sub first { print "A::first\n"; } sub second { print "A::second\n"; } sub check { my $this = shift; my $pkg = ref $this; print "\nResults of check:\n"; foreach my $subname (qw(first SUPER::first second SUPER::second)) +{ if (defined (my $sub = $this->can ($subname))) { print ("$pkg can $subname\n"); $this->$sub (); } else { print "$pkg cannot do $subname\n"; } } } package A_sub; @A_sub::ISA = qw(A); sub first { print "A_sub::first\n"; } sub check_sub { my $this = shift; my $pkg = ref $this; print "\nResults of check_sub:\n"; foreach my $subname (qw(first SUPER::first second SUPER::second)) +{ if (defined (my $sub = $this->can ($subname))) { print ("$pkg can $subname\n"); $this->$sub (); } else { print "$pkg cannot do $subname\n"; } } } package main; my $asub = new A_sub; $asub->check (); $asub->check_sub ();
This prints:

Results of check: A_sub can first A_sub::first A_sub cannot do SUPER::first A_sub can second A::second A_sub cannot do SUPER::second Results of check_sub: A_sub can first A_sub::first A_sub can SUPER::first A::first A_sub can second A::second A_sub can SUPER::second A::second
Did everybody out there know this? I was quite surprised of the result.

pike

Replies are listed 'Best First'.
Re: Re: Re: can('SUPER::defaults')
by demerphq (Chancellor) on Oct 23, 2001 at 16:25 UTC
    Suprising yes. Weird only sortof. This is documented behaviour, if a little counter intuitive:

    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:

    $self->SUPER::display('Height', 'Weight');
    Please note that the SUPER:: construct is meaningful only within the class.

    from PerlObj, emphasis added

    My guess why, and its only a guess, is that Perl resolves SUPER at compile time. It doesnt care about the object at all as that happens at runtime. OTOH, that explanation gives me a funny feeling, @ISA is being set at runtime so I am confused.

    Yves
    --
    You are not ready to use symrefs unless you already know why they are bad. -- tadmc (CLPM)

      I'd like to make you feel better by disagreeing, as oddly as that sounds.

      It *cannot* be resolved at compile time, because method calls are not resolved at compile time. (That's why prototypes don't work on methods, for example.)

      My guess, based on a very quick reading of gv.c (Perl_gv_fetchmeth), is that methods care about their stashes. In other words, the package where a method was defined matters, because that's the first place Perl looks when it's trying to resolve something like this (a variable name, a method call). gv_fetchmeth() attempts to find an appropriate method to call. When '::SUPER' is found, it looks in @ISA available in the current stash.

      That's modifiable at run time.

      I'm not completely convinced my explanation is right, but I will stake my autographed CowboyNeal photo that it's not compile time. (Now I sit back and wait for Dominus to whack me with a stick of -1, Pedantic and Slightly Incorrect. ;)

      IMHO stay away from can(). It is 'wrong' frequently enough to not be worth it. 'wrong' in quotes because as other people noted, the behavior is predictable but not DWIM. It will have undefined behavior if you are using AUTOLOAD as well, if you are binding subs at runtime onto packages. You may or may not have bound a sub to a package when can is called. You can work around this by calling $ob->foo, $ob->can('foo') so the AUTOLOAD always runs, but then if $ob->foo has side effects .. be afraid.

      -jackdied