{
package Foo;
sub foo { ... }
# autoloads bar()
# autoloads baz()
}
{
package Bar;
@ISA = Foo::;
# autoloads foo()
# autoloads bar()
}
####
my $code = $obj->can('foo');
$obj->$code(...)
##
##
$obj->foo(...)
##
##
AUTOLOAD {
...;
if (should_autoload($method)) {
...
}
else {
croak("No method $method ...");
}
}
##
##
AUTOLOAD {
...;
if (should_autoload($method)) {
...
}
elsif (my $code = $self->can('SUPER::AUTOLOAD')) {
goto &$code;
}
else {
croak("No method $method ...");
}
}
##
##
AUTOLOAD {
my $self = $_[0]; # Not shift, using goto.
my $method = ...;
if (my $code = _autoloaded($self, $method)) {
goto &$code;
}
elsif (my $next = next_autoload($self)) {
goto &$next;
}
elsif ($method eq 'DESTROY') {
# If people do $obj->DESTROY and there's no
# DESTROY available then they'll be surprised.
# Just as surprised I am that they call DESTROY
# explicitly.
return;
}
else {
croak(...);
}
}
##
##
sub can {
my ($self, $method) = @_; # Not shift, using goto.
# The call to UNIVERSAL::can() should be inside an eval EXPR
# to get caller info right for when $method =~ /^SUPER::/,
# if can() is exported (see Class::AUTOCAN below).
my $universal = UNIVERSAL::can($self, $method);
if (not defined $universal) {
if (my $code = _autoloaded($self, $method)) {
return $code;
}
}
if (my $next = $self->next::can) {
goto &$next
}
return $universal; # May be undefined.
}
##
##
use Class::AUTOCAN sub {
my $self = shift;
my ($method) = @_;
if ($method =~ /^auto_/) {
return sub {
my $self = shift;
return "$self called $method";
};
}
return;
};
##
##
Class::AUTOCAN->install(
target => $pkg,
code => sub { ... },
);