in reply to How to call AUTOLOAD before @ISA?

I am pretty sure (but not positive) the answer is: No, this cant be done.

Calling AUTOLOAD before your parent functions sort of defeats the purpose of inheritance. If this were the case, a parent function would never get called because the AUTOLOAD would get called first. AUTOLOAD is a last ditch effort when *all* else fails, so if perl cannot find the function in the class or anywhere in chain of parents it will call the first AUTOLOAD it finds.

I would recommend just moving the AUTOLOAD to the parent. Or not give the class a parent if you think the class needs to have an AUTOLOAD function.

Another idea is instead of total inheritance you can do cheesy selective pseudo-inheritance, ie only grab the functions you want like:
package B; *new = \&A::new; sub AUTOLOAD { print "autoload in B, called as $AUTOLOAD\n"; }
So now your main will do what you want. I have just made &A::new synonomous with &B::new in the symbol table so you only have to maintain one new function. I dont this this would be too much work to just alias the symbols for each function that you want.

Replies are listed 'Best First'.
RE: Re: How to call AUTOLOAD before @ISA?
by ZZamboni (Curate) on May 10, 2000 at 05:20 UTC
    But the thing is that I want to inherit all the methods from the superclass, but I only want to call them in a controlled fashion from AUTOLOAD when certain conditions are met. My idea was to do something like this:
    sub AUTOLOAD { my $self=shift; my $method=$AUTOLOAD; $method=~s/^.*:://; if (certain conditions are met) { do something } else { $self->SUPER::$method(@_); } }
    The thing is that the check and the "do something" are all the same, but this applies to several methods, that's why I wanted to use AUTOLOAD.

    I'm also pretty sure that this cannot be done (all the documentation seems to indicate so) and I have already solved my problem by dynamically defining the necessary subroutines in B's BEGIN block, but I will be glad to hear any other ideas.

    Thanks,

    --ZZamboni

      There are a couple of other ways to get around this. If you're comfortable mucking about in the symbol table, you can generate your subroutines from a template (especially the "do some checks here" code) and eval() them into being the first time they're needed. I'd do that in a BEGIN block, perhaps. Another option is, of course, delegation -- probably the best approach.

      You could also fake inheritance, by not using @ISA, and hard-coding calls to the parent. That would allow you to use AUTOLOAD to generate them. You could even write a dispatcher method, to do all the checks for you, then find the appropriate subroutine. You'd have to pass the name of a method you want, and you could use a hash of sub refs to avoid symbolic references. That's not a bad solution.

      But there's no way I'm aware of to call AUTOLOAD before checking the inheritance tree. Code provided for any of these examples if you're really curious.

      well this is an obvious solution (okay maybe only obvious to my cloudy little mind):
      sub AUTOLOAD { my $self=shift; my $method=$AUTOLOAD; my $PSEUDO_PARENT = 'A'; $method=~s/^.*:://; return if $method eq 'DESTROY'; if (certain conditions are met) { do something } else { #dynamically call the pseudo parent function my $return_value = eval("&{$PSEUDO_PARENT"."::"."$method}".'($s +elf, @_)'); #catch eval error! if( $@ ) { die $@; } #return whatever the eval'd function returned return $return_value; } }
      The problem with this is hardcoding the parent class in, instead of using SUPER. And with a combination of eval and AUTOLOAD you are sure to not the the optimal performance.