use strict; use warnings; use Data::Dump qw/pp dd/; package FOO { sub foo { warn __PACKAGE__."::foo";}; sub bar { warn __PACKAGE__."::bar";} sub baz { warn __PACKAGE__."::baz";} }; package BAR { our @ISA = qw/FOO/; sub bar { warn __PACKAGE__."::bar";} sub can { my ( $self,$sym ) = @_ ; warn "Calling can in ".__PACKAGE__." for ".Data::Dump::pp $self; FOO->can($sym); } }; package BAZ { our @ISA = qw/BAR/; sub baz { warn __PACKAGE__."::baz";} sub can { my ( $self,$sym ) = @_ ; warn "Calling can in ".__PACKAGE__." for ".Data::Dump::pp $self; BAR->can($sym); } sub new { my ( $self,@args ) = @_ ; bless {@args} , __PACKAGE__; } }; package main; use Test::More; my $obj = BAZ->new(name=>"OBJ"); for my $sym (qw/foo bar baz/) { diag "****** Trying can($sym)"; diag "... as ->meth\n"; my $meth = $obj->can($sym); $obj->$meth() if $meth; diag "... as sub()\n"; my $sub = UNIVERSAL::can($obj,$sym); $obj->$sub() if $sub; is($meth,$sub,"same for $sym"); } done_testing;