use NEXT;
package A;
sub A::method { print "$_[0]: A method\n"; $_[0]->NEXT::method() }
sub A::DESTROY { print "$_[0]: A dtor\n"; $_[0]->NEXT::DESTROY() }
package B;
use base qw( A );
sub B::AUTOLOAD { print "$_[0]: B AUTOLOAD\n"; $_[0]->NEXT::AUTOLOAD() }
sub B::DESTROY { print "$_[0]: B dtor\n"; $_[0]->NEXT::DESTROY() }
package C;
sub C::DESTROY { print "$_[0]: C dtor\n"; $_[0]->NEXT::DESTROY() }
package D;
@D::ISA = qw( B C E );
sub D::method { print "$_[0]: D method\n"; $_[0]->NEXT::method() }
sub D::AUTOLOAD { print "$_[0]: D AUTOLOAD\n"; $_[0]->NEXT::AUTOLOAD() }
sub D::DESTROY { print "$_[0]: D dtor\n"; $_[0]->NEXT::DESTROY() }
sub D::oops { print "$_[0]: D oops\n"; $_[0]->NEXT::method() }
package E;
@E::ISA = qw( F G );
sub E::method { print "$_[0]: E method\n";
$_[0]->NEXT::method();
$_[0]->NEXT::method() }
sub E::AUTOLOAD { print "$_[0]: E AUTOLOAD\n"; $_[0]->NEXT::AUTOLOAD() }
sub E::DESTROY { print "$_[0]: E dtor\n"; $_[0]->NEXT::DESTROY() }
package F;
sub F::method { print "$_[0]: F method\n"; }
sub F::AUTOLOAD { print "$_[0]: F AUTOLOAD\n"; }
sub F::DESTROY { print "$_[0]: F dtor\n"; }
package G;
sub G::method { print "$_[0]: G method\n"; $_[0]->NEXT::method() }
sub G::AUTOLOAD { print "$_[0]: G AUTOLOAD\n"; $_[0]->NEXT::AUTOLOAD() }
sub G::DESTROY { print "$_[0]: G dtor\n"; $_[0]->NEXT::DESTROY() }
package main;
my $obj = bless {}, "D";
print "\nRedispatch actual methods:\n";
$obj->method();
print "\nRedispatch actual methods again (should be identical):\n";
$obj->method();
print "\nRedispatch AUTOLOADed methods:\n";
$obj->missing_method();
print "\nNamed method can't redispatch to named method of different name:\n";
eval { $obj->oops() } || print $@;
eval q{
package C;
sub AUTOLOAD { print "$_[0]: C AUTOLOAD\n"; $_[0]->NEXT::method() };
};
print "\nAUTOLOADed method can't redispatch to named method:\n";
eval { $obj->missing_method(); } || print $@;
eval q{
package C;
sub method { print "$_[0]: C method\n"; $_[0]->NEXT::AUTOLOAD() };
};
print "\nNamed method can't redispatch to AUTOLOADed method:\n";
eval { $obj->method(); } || print $@;
print "\nBase class methods only redispatched within hierarchy:\n";
my $ob2 = bless {}, "B";
$ob2->method();
$ob2->missing_method();
print "\nCan redispatch destructors:\n";