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