sub foo { my ($self) = @_; croak "..." unless ref($self) && $self->isa("AnInterface") } #### sub foo # requires interfaces InterfaceA, InterfaceB { my ($self) = @_; InterfaceA::validate($self); InterfaceB::validate($self); } #### sub InterfaceA::validate { my ($candidate) = @_; error unless ref($candidate); error unless $candidate->isa("InterfaceA"); # explicit ISA } sub InterfaceB::validate { my ($candidate) = @_; error unless ref($candidate); error unless $candidate->can("fn1"); # implicit ISA error unless $candidate->can("fn2"); } #### sub validate_object { my ($self, @interfaces) = @_; error unless ref($self); foreach my $interface (@interfaces) { my $fn = $interface . "::is_implemnted_by"; error unless $fn->($self); } } #... sub foo { my ($self) = @_; validate_object($self, qw/InterfaceA InterfaceB InterfaceC/); } sub bar { my ($self) = @_; validate_object($self, map {"Interface$_"} qw/A B D/); }