I'm in need of "runtime decorators". That is, a class whose constructor is to take an instance of either the base class or a separate "runtime decorator" and add functionality to it. I don't know ahead of time what the type of the object will be.
Here's an extremely contrived example of what I want to do (this strategy makes sense in the actual problem domain).
package Base;
sub new {
my $package = shift;
my $id = shift;
return bless {
id => $id,
}, $package;
}
sub id {
my ($self, $id) = @_;
$self->{id} = $id if defined $id;
return $self->{id};
}
1;
package NameDecorator;
sub new {
my $package = shift;
my $base_or_decorated = shift;
my $self = $base_or_decorated->new(@_);
$self->{name} = undef;
return $self->{name};
}
sub name {
my ($self, $name) = @_;
$self->{name} = $name if defined $name;
return $self->{name};
}
1;
...do the same for an AgeDecorator
Then I could use it like follows
use Base;
use NameDecorator;
use AgeDecorator;
my $decorated = AgeDecorator->new(NameDecorator->new(Base->new('id1'))
+);
$decorated->name('Edith');
$decorated->age(93);
I need the flexibility to be able to chain decorators together and still have available to methods added from the decorator before it.
Is there a name for what I'm trying to do and can this be done easily without the help of a module or is there a module which can help me achieve this?
UPDATE:
This is getting closer to what I want, but it still adds to the class rather than the object
package NameProto;
use strict;
use base qw(Base::Decorator);
sub new {
my $self = shift->SUPER::new(@_);
$self->{age} = 0;
no strict 'refs';
my $package = ref($self->{base});
*{$package . '::name'} = sub {
my ($self, $name) = @_;
$self->{name} = $name if defined $name;
return $self->{name};
};
return bless $self, $package;
}
sub name {
return shift->{base}->name(@_);
}
1;