package Wrapper; sub new { my ($class, $wrappee) = @_; bless { wrappee => $wrappee }, $class; } sub AUTOLOAD { my ($self, @args) = @_; my ($sub) = $AUTOLOAD =~ /([^:])$/; my $type = ...; # figured from other info $self->wrap($sub, $type, @args); } sub wrap { my ($self, $sub, $type, @args) = @_; if ($type = 'A') { $self->wrap_A($sub, @args); } elsif ($type = 'B') { $self->wrap_B($sub, @args); } elsif ($type = 'C') { $self->wrap_C($sub, @args); } else { die "Bad type $type"; } } # defaults just pass call onto wrappee. sub wrap_A { ... } sub wrap_B { ... } sub wrap_C { ... } package Wrapper::First; use base 'Wrapper'; # overrides wrap to wrap all method types sub wrap { ... } package Wrapper::Second; use base 'Wrapper'; # overrides wrap_B to wrap all methods of type B sub wrap_B { ... }