sub AUTOLOAD { # attrs my ($self) = @_; (my $attr = $AUTOLOAD) =~ s/^.*:://; return if $attr eq 'DESTROY'; return $self->{$attr} if(exists $self->{$attr}); return $self->{prototype}->$attr if(exists $self->{prototype}); } =item new Create a new Slot with prototyping. # class method my $proto = SD::Slot->new({ min_val => 1, max_val => 10 }); # $slot is blessed as an SD::Slot and has prototype = $proto my $slot = $proto->new({ min_val => 0 }); # $slot2 isa SD::Slot::Multi but still has prototype = $proto my $slot2 = SD::Slot::Multi->new({ prototype => $proto }); The parameter hashref is blessed into the appropriate class and returned. =cut sub new { my ($class, $proto, $self); # @_ processed conditionally if($class = ref $_[0]) { $proto = shift; # we have a prototype object } else { $class = shift; } $self = shift || {}; if(!exists $self->{prototype} && $proto) { $self->{prototype} = $proto; } bless $self => $class; } # example use (config) my %prototypes; $prototypes{int} = SD::Slot->new({ widget => 'textfield', constraints => [ \&SD::Constraints::integer_rx, \&SD::Constraints::min_val, \&SD::Constraints::max_val, ], }); $prototypes{int1_10} = $prototypes{int}->new({ prototype => $prototypes{int}, skip_warn => 1, min_val => 1, max_val => 10, }); my %slots; $slots{intelligence} = $prototypes{int1_10}->new({ name => 'intelligence', mandatory => 1, constraints => [ # add extra constraint @{ $prototypes{int}->constraints }, sub { $_[1] % 2 or die E->new( "Not an odd number '$_[1]'") }, ], });