One possibility is to use method modifiers, which are provided by object systems like Moose or Moo:
use strict; use warnings;
package Child {
use Moose;
sub method_x { warn "call method_x" }
sub method_y { warn "call method_y" }
sub method_z { warn "call method_z" }
}
package Parent {
use Moose;
has child => (is => 'rw');
sub x { shift->child->method_x(@_) }
sub y { shift->child->method_y(@_) }
sub z { shift->child->method_z(@_) }
# A method modifier in action
after [qw/ x y z /] => sub {
warn "called after every Parent (!) invocation";
};
}
my $p = Parent->new(child => Child->new);
$p->x; $p->y; $p->z;
Output:
call method_x at - line 7.
called after every Parent (!) invocation at - line 23.
call method_y at - line 8.
called after every Parent (!) invocation at - line 23.
call method_z at - line 9.
called after every Parent (!) invocation at - line 23.
If you actually wish to wrap all the methods of Child
, use a subclass:
package WrappedChild {
use Moose;
extends 'Child';
# the /(?=)/ regex matches always
after qr/(?=)/ => sub {
warn "called after each method in Child";
};
}
my $p = Parent->new(child => WrappedChild->new);
$p->x; $p->y; $p->z;
This produces
called after each method in Child at - line 32.
called after each method in Child at - line 32.
called after each method in Child at - line 32.
called after each method in Child at - line 32.
called after each method in Child at - line 32.
called after each method in Child at - line 32.
call method_x at - line 7.
called after each method in Child at - line 32.
called after every Parent (!) invocation at - line 22.
call method_y at - line 8.
called after each method in Child at - line 32.
called after every Parent (!) invocation at - line 22.
call method_z at - line 9.
called after each method in Child at - line 32.
called after every Parent (!) invocation at - line 22.
called after each method in Child at - line 32.
called after each method in Child at - line 32.
called after each method in Child at - line 32.
which might be a bit excessive. Sticking to explicit names might be preferable.
See Moose::Manual::MethodModifiers
for more info.
If you do not wish to use any modules, you can hack your way through the jungle symbol table:
for my $name (qw/method_x method_y method_z/) {
no strict 'refs';
no warnings 'redefine';
my $orig = \&{"Child::$name"};
*{"Child::$name} = sub {
my @return_values = wantarray ? $orig->() : scalar $orig->();
warn "called after each method";
return wantarray ? @return_values : $return_values[0];
};
}
Output:
call method_x at - line 7.
called after each method at - line 31.
call method_y at - line 8.
called after each method at - line 31.
call method_z at - line 9.
called after each method at - line 31.