package Foo; my %attrs = map { $_ => 1 } qw/ this that /; AUTOLOAD { my ($m) = our $AUTOLOAD =~ /.*::(.*)/s; return if $m eq 'DESTROY'; if ($attrs{$m}) { print "OK: $m"; } else { print "Failure: $m"; # Here you need to emulate perl error message. # Note that you don't want to use the Carp # module for this. } } #### Foo::->this; # OK: this Foo::->that; # OK: that Foo::->these; # Failure: these #### package Foo::Bar; use base 'Foo'; my %attrs = map { $_ => 1 } qw/ hah heh /; AUTOLOAD { my ($m) = our $AUTOLOAD =~ /.*::(.*)/s; return if $m eq 'DESTROY'; if ($attrs{$m}) { print "OK: $m"; } else { print "Failure: $m"; } } #### Foo::Bar::->hah; # OK: hah Foo::Bar::->heh; # OK: heh Foo::Bar::->hoh; # Failure: hoh #### Foo::Bar::->this; # Failure: this Foo::Bar::->that; # Failure: that #### package Foo::Bar; use base 'Foo'; my %attrs = map { $_ => 1 } qw/ hah heh /; AUTOLOAD { my ($m) = our $AUTOLOAD =~ /.*::(.*)/s; return if $m eq 'DESTROY'; if ($attrs{$m}) { print "OK: $AUTOLOAD"; } else { my $self = shift; if ($self->can('SUPER::AUTOLOAD')) { return $self->${\"SUPER::$m"}(@_); } else { print "Failure: $AUTOLOAD"; } } } #### { package A; my %attrs = map { $_ => 1 } qw/ xism /; AUTOLOAD { my ($m) = our $AUTOLOAD =~ /.*::(.*)/s; return if $m eq 'DESTROY'; if ($attrs{$m}) { print "OK: $AUTOLOAD"; } else { print "Failure: $AUTOLOAD"; } } } { package B; my %attrs = map { $_ => 1 } qw/ yism /; AUTOLOAD { my ($m) = our $AUTOLOAD =~ /.*::(.*)/s; return if $m eq 'DESTROY'; if ($attrs{$m}) { print "OK: $AUTOLOAD"; } else { print "Failure: $AUTOLOAD"; } } } #### A::->xism; # OK: A::xism B::->yism; # OK: B::yism #### package AB; use base 'A', 'B'; #### AB::->xism; # OK: AB::xism AB::->yism; # Failure: AB::yism