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/);
}