Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

tracing SUPER

by Ranger Rick (Novice)
on Jul 28, 2004 at 17:46 UTC ( #378131=perlquestion: print w/replies, xml ) Need Help??

Ranger Rick has asked for the wisdom of the Perl Monks concerning the following question:

Hello, monks,

I've inherited (hah) some very large mod_perl code that uses inheritance heavily. I've run into a bug with a subroutine that performs form validation which calls $self->SUPER::validate(). i.e., something like:

sub validate { my $self = shift; # do validation return $self->SUPER::validate(@_); }

All of the validation that occurs inside this subroutine works, and is fine and dandy, but the "return $self->SUPER::validate(@_);" part returns false when it shouldn't. I can't for the life of me, however, find where that other validate is being called. Short of changing the tens (hundreds?) of other related @ISA's that have a validate subroutine, is there an easy way to trace this inside mod_perl?

Replies are listed 'Best First'.
Re: tracing SUPER
by ysth (Canon) on Jul 28, 2004 at 22:36 UTC
    Just a comment; SUPER:: has nothing to do with the object; it's purely syntactic sugar to look up the current package's first @ISA element.

    Witness:

    use strict; use warnings; @Foo::ISA = "Bar"; @Baz::ISA = "Quux"; sub Bar::phrenia { print "In Bar::phrenia\n" } sub Quux::phrenia { print "In Quux::phrenia\n" } package Foo; sub Baz::schizo { my $self = shift; $self->SUPER::phrenia(); } package main; my $obj = bless {}, "Baz"; $obj->schizo();
    This produces "In Bar::phrenia", where Bar isn't even in $obj's inheritance tree.
Re: tracing SUPER
by lachoy (Parson) on Jul 28, 2004 at 20:26 UTC

    Class::ISA might be useful in this case -- you can just ask each class if it supports 'validate()' and if so print that out, like this untested:

    sub validate { my $self = shift; # do validation foreach my $parent_class ( Class::ISA::super_path( ref $self ) ) { if ( $parent_class->can( 'validate' ) ) { print "Will call '$parent_class->validate()'\n"; last; } } return $self->SUPER::validate(@_); }

    Chris
    M-x auto-bs-mode

Re: tracing SUPER
by fglock (Vicar) on Jul 28, 2004 at 17:55 UTC

    How about (untested):

    sub validate { my $self = shift; # do validation print STDERR "it is going to call $ISA[0] :: validate\n"; return $self->SUPER::validate(@_); }

    You should be able to see the Class name in the error log.

      Hmmm, that probably won't help much, because presumably the class knows who its direct ancestor is. It gets tricky with multiple inheritance and/or deep inheritance hierarchies, where it's just plain hard to tell from a casual glance who the next method is. Note how in this case there's no guarantee $ISA[0] ."::validate" exists.

      If you want to do that kind of analysis, though, the code in NEXT.pm might provide inspiration. Or deterrence :-)

        It's not that complicated. The "Perl Cookbook" says:

        Note that SUPER only works on the first overridden method. If your @ISA array has several classes, it only gets the first one.

      I may be confused about how delegation works, now that I think about it more. When something has @ISA = qw(Foo::Bar), the only thing it checks other than itself is Foo::Bar? Or does it look for anything else that isa(Foo::Bar) and call the method there as well? If that's the case, then I think it's failing altogether; We have a bunch of code that @ISA = qw(Foo::Bar) but there is no Foo/Bar.pm; it's just a convenience. If that is the case (you use SUPER, but one of your @ISA's doesn't exist), does it return a false value?
        Inheritance goes one way: up. If B and C are both As, and C->meth is called but C doesn't define a meth, B will certainly not be called! Why should it; after all, C is not a B.

        But you say you have "a bunch of code that @ISA = qw(Foo::Bar) but there is no Foo/Bar.pm; it's just a convenience". Convenience for what? It's wrong semantically to inherit from something that doesn't exist.

        Note that not having a file Foo/Bar.pm is perfectl all right: Foo::Bar may be defined in another file, or created on the fly at run time. So long that it is compiled before you call any of its methods, you are syntactically safe. You'd better make sure it finishes compiling before its subclasses are defined too, unless you know what you're doing (== funky dynamic stuff)

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://378131]
Approved by Enlil
Front-paged by broquaint
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (2)
As of 2019-12-12 06:53 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?