package src::bo::Duck; use strict; use warnings; use Carp; sub new { my $class = shift; my $self = { FLYBEHAVIOUR => { 'VALUE' => undef, 'ACCESS' => 'protected' }, QUACKBEHAVIOUR => { 'VALUE' => undef, 'ACCESS' => 'protected' }, }; my $closure = sub { my $field = shift; $self->{$field}->{'ACCESS'} eq 'private' and caller(0) eq __PACKAGE__ || confess "$field is private"; $self->{$field}->{'ACCESS'} eq 'protected' and caller(0)->isa(__PACKAGE__) || confess "$field is protected"; if ( @_ ) { $self->{$field}->{'VALUE'} = shift; } return $self->{$field}->{'VALUE'}; }; bless ($closure, $class); return $closure; } sub setFlyBehaviour { caller(0)->isa(__PACKAGE__) || confess "setFlyBehaviour is protected"; my $closure = shift; my $flyBehaviour = shift; &{ $closure }("FLYBEHAVIOUR", $flyBehaviour); } sub setQuackBehaviour { caller(0)->isa(__PACKAGE__) || confess "setQuackBehaviour is protected"; my $closure = shift; my $quackBehaviour = shift; &{ $closure }("QUACKBEHAVIOUR", $quackBehaviour); } sub doFly { my $closure = shift; &{ $closure }("FLYBEHAVIOUR")->fly(); } sub doQuack() { my $closure = shift; &{ $closure }("QUACKBEHAVIOUR")->quack(); } 1; #### my $self = { FLYBEHAVIOUR => { 'VALUE' => undef, 'ACCESS' => 'protected' }, QUACKBEHAVIOUR => { 'VALUE' => undef, 'ACCESS' => 'protected' }, }; #### my $closure = sub { my $field = shift; $self->{$field}->{'ACCESS'} eq 'private' and caller(0) eq __PACKAGE__ || confess "$field is private"; $self->{$field}->{'ACCESS'} eq 'protected' and caller(0)->isa(__PACKAGE__) || confess "$field is protected"; if ( @_ ) { $self->{$field}->{'VALUE'} = shift; } return $self->{$field}->{'VALUE'}; }; #### $whistle->("QUACKBEHAVIOUR", src::bo::behaviour::quack::CanQuack->new() ); #### sub setFlyBehaviour { caller(0)->isa(__PACKAGE__) || confess "setFlyBehaviour is protected"; my $closure = shift; my $flyBehaviour = shift; &{ $closure }("FLYBEHAVIOUR", $flyBehaviour); } sub setQuackBehaviour { caller(0)->isa(__PACKAGE__) || confess "setQuackBehaviour is protected"; my $closure = shift; my $quackBehaviour = shift; &{ $closure }("QUACKBEHAVIOUR", $quackBehaviour); } #### caller(0) eq __PACKAGE__ || confess "setQuackBehaviour is private"; #### package src::bo::Rubber; use strict; use warnings; use Carp; use src::bo::Duck; use base qw/src::bo::Duck/; use src::bo::behaviour::fly::CannotFly; use src::bo::behaviour::quack::CanSqeek; sub new { my $class = shift; my $extends = $class->SUPER::new( @_ ); $extends->setFlyBehaviour( src::bo::behaviour::fly::CannotFly->new() ); $extends->setQuackBehaviour( src::bo::behaviour::quack::CanSqeek->new() ); my $self = { COLOR => { 'VALUE' => undef, 'ACCESS' => 'protected' }, }; my $closure = sub { my $field = shift; if ( exists $self->{$field} ) { $self->{$field}->{'ACCESS'} eq 'private' and caller(0) eq __PACKAGE__ || confess "$field is private"; $self->{$field}->{'ACCESS'} eq 'protected' and caller(0)->isa(__PACKAGE__) || confess "$field is protected"; if ( @_ ) { $self->{$field}->{'VALUE'} = shift; } return $self->{$field}->{'VALUE'}; } else { return $extends->($field,@_); } }; bless ($closure, $class); return $closure; } sub setColor { my $closure = shift; my $color = shift; &{ $closure }("COLOR", $color ); } sub getColor { my $closure = shift; &{ $closure }("COLOR"); } 1; #### sub new { my $class = shift; my $extends = $class->SUPER::new( @_ ); $extends->setFlyBehaviour( src::bo::behaviour::fly::CannotFly->new() ); $extends->setQuackBehaviour( src::bo::behaviour::quack::CanSqeek->new() ); my $self = { COLOR => { 'VALUE' => undef, 'ACCESS' => 'protected' }, }; my $closure = sub { my $field = shift; if ( exists $self->{$field} ) { $self->{$field}->{'ACCESS'} eq 'private' and caller(0) eq __PACKAGE__ || confess "$field is private"; $self->{$field}->{'ACCESS'} eq 'protected' and caller(0)->isa(__PACKAGE__) || confess "$field is protected"; if ( @_ ) { $self->{$field}->{'VALUE'} = shift; } return $self->{$field}->{'VALUE'}; } else { return $extends->($field,@_); } }; bless ($closure, $class); return $closure; }