There is probably a better way to do this. (Likely on CPAN.) Plus this is slow. But here is a very simple implementation of a different inheritance scheme than the one that Perl uses. This is based on each object being its
own class. Call the def method to add new methods to the
object. Call new to generate an object that inherits from
the parent. Call "call" to call methods you have inherited,
or just call them directly. There is a basic search mechanism. Multiple inheritance is not supported. Methods
follow the usual Perl semantics. (The first argument is the object, the rest are arguments to the method.)
package ObjectClass;
use Carp;
use strict;
use vars qw($AUTOLOAD);
sub call {
my $self = shift;
my $meth = $self->find_meth(shift);
$meth->(@_);
}
sub def {
my $self = shift;
{
my $meth = shift;
my $implement = shift;
$self->{meth_cache}->{$meth} = $implement;
redo if @_;
}
}
sub find_meth {
my $self = shift;
my $meth = shift;
my $cache = $self->{meth_cache};
if (exists $cache->{$meth}) {
return $cache->{$meth};
}
elsif (exists $self->{proto}) {
return $self->{proto}->find_meth($meth);
}
else {
confess ("Object does not implement method '$meth'");
}
}
sub new {
my $proto = shift;
# Note for Merlyn, this time it is not cargo-cult programming! :-P
unless (ref($proto)) {
my $class = $proto;
$proto = { meth_cache => {}, };
bless($proto, $class);
}
my $self = { meth_cache => {}, proto => $proto };
bless $self, ref($proto);
}
sub AUTOLOAD {
my $self = shift;
$AUTOLOAD =~ s/.*:://;
return if $AUTOLOAD eq "DESTROY";
$self->call($AUTOLOAD, @_);
}
package main;
# A simple test
my $parent = new ObjectClass;
$parent->def("hello", sub {print "Hello world\n"});
my $child = $parent->new();
$child->def("goodbye", sub {print "Goodbye\n"});
$parent->hello(); # Calling the defining object
$child->hello(); # Inherit the method
$child->goodbye(); # Method in the subclass
$parent->goodbye(); # Blows up.
Does this make your mock classes easier to implement?
UPDATE
I did this mostly because I thought it would be fun to
write. If you want to use this idea, I would suggest
looking at Class::Classless or Class::SelfMethods.