use warnings; use strict; package Foo::Bar; our $crHandler = sub { print "$_[0]: default handler called.\n"; }; sub doA1 { print "Doing A1 for $_[1]\n"; &$crHandler('A1'); } sub doB1 { print "Doing B1 for $_[1]\n"; &$crHandler('B1'); } sub doA2 { print "Doing A2 for $_[1]\n"; &$crHandler('A2'); } sub doB2 { print "Doing B2 for $_[1]\n"; &$crHandler('B2'); } #### use warnings; use strict; package Foo::Baz; #----------------------------------------------- # import specially wrapped methods from Foo::Bar # that call custom handler and default to user # define global handler #----------------------------------------------- BEGIN { my $CLASS = __PACKAGE__; require Foo::Bar; # generates wrapper sub sub wrapAndCall { my $crCall = shift; my $crCustom = shift; my $crOriginal = $Foo::Bar::crHandler; local $Foo::Bar::crHandler = sub { return if (&$crCustom(@_)); if (defined($crOriginal)) { &$crOriginal(@_); } else { print "Original global handler undefined.\n"; } }; return &$crCall(@_); } # some custom handlers # return 1 if completely handled # return 0 if pass through to original global handler # for further processing my $crCustomHandler1 = sub { print "$_[0]: custom handler 1 called.\n"; return 0; }; my $crCustomHandler2 = sub { print "$_[0]: custom handler 2 called.\n"; return 0; }; # manufacture and assign the wrappers { no strict 'refs'; #import all of the subs using custom handler 1 foreach my $sMethod (qw(doA1 doB1)) { *{"${CLASS}::$sMethod"} = sub { return wrapAndCall(*{"Foo::Bar::$sMethod"} , $crCustomHandler1, @_); }; } #import all of the subs using custom handler 2 foreach my $sMethod (qw(doA2 doB2)) { *{"${CLASS}::$sMethod"} = sub { return wrapAndCall(*{"Foo::Bar::$sMethod"} , $crCustomHandler2, @_); }; } } } #----------------------------------------------- # define the rest of the methods #----------------------------------------------- sub new { return bless([], shift); } #----------------------------------------------- # module return #----------------------------------------------- return 1; #### use warnings; use strict; use Foo::Baz; my $oFoo = Foo::Baz->new(); print "created \$oFoo=<$oFoo>\n"; print "\n**demoing default global handler**\n"; $oFoo->doA1('Ayelet (deer)'); print "\n**undefining global handler**\n"; $Foo::Bar::crHandler = undef; $oFoo->doA2('Mayan (spring)'); print "\n**reassigning global handler to non-default sub**\n"; $Foo::Bar::crHandler = sub { print "$_[0]: replacement handler called\n"; }; $oFoo->doB2('Dov (bear)');