http://qs321.pair.com?node_id=792476


in reply to Re^3: A working strategy to handle AUTOLOAD, can(), and (multiple) inheritance without touching UNIVERSAL?
in thread A working strategy to handle AUTOLOAD, can(), and (multiple) inheritance without touching UNIVERSAL?

As the thread here on PM and the two CPAN modules (written by notable Perl people) suggests, this is not as easy as it looks. I think the best way to get it right each time is to find an approach that always acts as "expected", and then put it in a module. I trust a module to be more consistent than me when faced with a repeated problem. :-)

Regarding your suggestions; it fails to behave like I would expect when it is inherited (and upon object destruction, but to be fair you do not have a constructor).

{ package Foo; sub can { my $self = shift; my $method = shift; return sub { print __PACKAGE__ . ": autoloaded $method\n" }; } sub AUTOLOAD { my $code = $_[0]->can(our($AUTOLOAD) =~ /.*::(.*)/s); goto &$code; } } { package Bar; our @ISA = Foo::; sub new { bless {} => shift } sub bar { print __PACKAGE__ . ": bar\n" } } my $o = Bar::->new; my $m = $o->can('bar'); $o->$m; $o->bar; __END__ Foo: autoloaded bar Bar: bar Foo: autoloaded DESTROY
In my solution outlined in the root node I handle it by moving the logic that generates the autoloaded subroutine reference to a common routine that both AUTOLOAD and can use. Then I see if UNIVERSAL::can returns anything. If it does it means that AUTOLOAD will not be invoked for $o->bar, so the return value of UNIVERSAL::can should be used instead. (This of course assumes that UNIVERSAL::can is not overloaded to do something else.)

The remaining logic in the root node is to handle when you use AUTOLOAD in a child class and the parent class also uses AUTOLOAD. This is even rarer, but it is still possible. As you say, it is important to trust a module to handle all edge cases so that you don't end up spending your evening debugging due to the module.

lodin