Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

AUTOLOAD cascade

by shemp (Deacon)
on Oct 13, 2004 at 16:15 UTC ( [id://398906]=perlquestion: print w/replies, xml ) Need Help??

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

2 Updates (at the bottom)

I have 2 classes, one inherits from the other, call them Parent and Child (Child inherits from Parent), and Parent has an AUTOLOAD method, and so does Child. The problem is that an instance of Child will never call Parent::AUTOLOAD, because of the call heirarchy. For instance:

package Parent; ... sub AUTOLOAD { my $self = shift @_; (my $method = $AUTOLOAD) =~ s/^.*:://; return if $method eq "DESTROY"; if ( $method eq 'parent_method' ) { # do something } } ... package Child; ... sub AUTOLOAD { my $self = shift @_; (my $method = $AUTOLOAD) =~ s/^.*:://; return if $method eq "DESTROY"; if ( $method eq 'child_method' ) { # do something } }
So, when i have an instance of Child, and call parent_method() on it, there is no parent_method() found in Child, then its not found in Parent, then its not found in UNIVERSAL. But then, Child::AUTOLOAD() is found, and is invoked. But that AUTOLOAD doesnt know about parent_method(), so does nothing, and Parent::AUTOLOAD() is not invoked. To get around this, im thinking i should add a line to the end of Child::AUTOLOAD() like this:
package Child; ... sub AUTOLOAD { my $self = shift @_; (my $method = $AUTOLOAD) =~ s/^.*:://; return if $method eq "DESTROY"; if ( $method eq 'child_method' ) { # do something } ... else { $self->SUPER::AUTOLOAD($method, @_); } }
Is this the proper way to do this, or am i missing something obvious?

Thanks much, as always.

Update: I found that i need to modify Parent::AUTOLOAD() too, so im thinking there is a better way than this, but heres the parent modification:

package Parent; ... sub AUTOLOAD { my $self = shift @_; my $method; if ( defined $AUTOLOAD ) { ($method = $AUTOLOAD) =~ s/.*:://; } else { $method = shift @_; } ... }
This had to be done because $Parent::AUTOLOAD is not set like for a normal call to AUTOLOAD, so i had to do something to get Parent::AUTOLOAD() to know what method to use.

Update 2:
I came up with a better way to do this, which doesnt require modifying Parent::AUTOLOAD():

# in Child::AUTOLOAD() # instead of $self->SUPER::AUTOLOAD($method, @_); my $super_method = 'SUPER::' . $method; $self->$super_method(@_);
The only thing about this one is that Perl will search through Parent and its parents, before calling Parent::AUTOLOAD(), which is a little more time consuming, but i am going to have the AUTOLOADS screw with the symbol tables and install AUTOLOAD'ed methods after their first invocation, which will speed things up.

Replies are listed 'Best First'.
Re: AUTOLOAD cascade
by blokhead (Monsignor) on Oct 13, 2004 at 16:38 UTC
    You can just prepend "SUPER::" to the method name and call it on the object again:
    if ($method eq 'child_method') { print "Child->child_method\n"; } else { $method = "SUPER::$method"; $self->$method(@_); }
    This works just fine for me, and does all the appropriate AUTOLOAD business.

    blokhead

Re: AUTOLOAD cascade
by Ven'Tatsu (Deacon) on Oct 13, 2004 at 16:51 UTC
    Another option is to use the sub NAME; stub declaration to force AUTOLOAD to start in the correct package.
Re: AUTOLOAD cascade
by JediWizard (Deacon) on Oct 13, 2004 at 16:28 UTC

    Sounds to me like you should look at the NEXT package.

    May the Force be with you
Re: AUTOLOAD cascade
by diotalevi (Canon) on Oct 13, 2004 at 17:14 UTC

    It sounds to me like you should eschew AUTOLOAD and just generate your methods as soon as your program is able to do so. If that is during compilation, generate them during BEGIN. If that is at runtime, perhaps after accessing a database, generate them when you connect.

    Unless there is a good reason, methods shouldn't be created at their moment of invocation. Its just bad practice.

      ...methods shouldn't be created at their moment of invocation. Its just bad practice

      Why?

      It would only happen at the moment of first invocation, subsequent invocations would just be normal method calls.

      Conversely, if the method is never called, it is never created, which might be a good thing?


      Examine what is said, not who speaks.
      "Efficiency is intelligent laziness." -David Dunham
      "Think for yourself!" - Abigail
      "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
        Until the code required to do it is so convoluted that you have to post on Perlmonks just to fix the first bug you found, having no idea what other bugs are lurking in the wings.

        Fooling around with the symbol table is akin to messing with dragons. You don't want to do that because you are crunchy and taste good with ketchup.

        Being right, does not endow the right to be rude; politeness costs nothing.
        Being unknowing, is not the same as being stupid.
        Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
        Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others scrutinizing the Monastery: (3)
As of 2024-04-20 12:01 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found