inject methods into a superclass instead of the class itself
This commit is contained in:
parent
9178c4e274
commit
d852c58a90
2 changed files with 18 additions and 19 deletions
|
|
@ -24,6 +24,8 @@ use Sub::Name ();
|
||||||
use Clone ();
|
use Clone ();
|
||||||
use mro ();
|
use mro ();
|
||||||
|
|
||||||
|
my $gen_package = 0;
|
||||||
|
|
||||||
sub import {
|
sub import {
|
||||||
my $class = shift;
|
my $class = shift;
|
||||||
if (! @_) {
|
if (! @_) {
|
||||||
|
|
@ -33,6 +35,9 @@ sub import {
|
||||||
my $caller = caller;
|
my $caller = caller;
|
||||||
# ensure we are using c3 method resolution
|
# ensure we are using c3 method resolution
|
||||||
mro::set_mro($caller, 'c3');
|
mro::set_mro($caller, 'c3');
|
||||||
|
$gen_package++;
|
||||||
|
my $super = __PACKAGE__ . '::_gen' . $gen_package;
|
||||||
|
mro::set_mro($super, 'c3');
|
||||||
|
|
||||||
# construct an ordered list and hash of the properties
|
# construct an ordered list and hash of the properties
|
||||||
my @propertyList;
|
my @propertyList;
|
||||||
|
|
@ -52,26 +57,18 @@ sub import {
|
||||||
# accessors for properties
|
# accessors for properties
|
||||||
for my $property ( @propertyList ) {
|
for my $property ( @propertyList ) {
|
||||||
no strict 'refs';
|
no strict 'refs';
|
||||||
$class->_install($caller, $property, sub {
|
$class->_install($super, $property, sub {
|
||||||
if (@_ > 1) {
|
if (@_ > 1) {
|
||||||
my $value = $_[1];
|
my $value = $_[1];
|
||||||
# call _set_$property with set value and use return value for actual value
|
|
||||||
if (my $set = $_[0]->can('_set_' . $property)) {
|
|
||||||
$value = $_[0]->$set($value);
|
|
||||||
}
|
|
||||||
return $_[0]{properties}{$property} = $value;
|
return $_[0]{properties}{$property} = $value;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
# call _get_$property and use return
|
|
||||||
if (my $get = $_[0]->can('_get_' . $property)) {
|
|
||||||
return $_[0]->$get($_[1]);
|
|
||||||
}
|
|
||||||
return $_[0]{properties}{$property};
|
return $_[0]{properties}{$property};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
$class->_install($caller, 'getProperty', sub {
|
$class->_install($super, 'getProperty', sub {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $property = shift;
|
my $property = shift;
|
||||||
if (exists $properties{$property}) {
|
if (exists $properties{$property}) {
|
||||||
|
|
@ -89,7 +86,7 @@ sub import {
|
||||||
return $self->maybe::next::method($property);
|
return $self->maybe::next::method($property);
|
||||||
});
|
});
|
||||||
|
|
||||||
$class->_install($caller, 'getProperties', sub {
|
$class->_install($super, 'getProperties', sub {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my %props = map { $_ => 1 } @propertyList;
|
my %props = map { $_ => 1 } @propertyList;
|
||||||
# remove any properties from superclass list that exist in this class
|
# remove any properties from superclass list that exist in this class
|
||||||
|
|
@ -98,7 +95,7 @@ sub import {
|
||||||
return @allProperties;
|
return @allProperties;
|
||||||
});
|
});
|
||||||
|
|
||||||
$class->_install($caller, 'getAttribute', sub {
|
$class->_install($super, 'getAttribute', sub {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $attribute = shift;
|
my $attribute = shift;
|
||||||
if ( exists $definition->{$attribute} ) {
|
if ( exists $definition->{$attribute} ) {
|
||||||
|
|
@ -108,10 +105,12 @@ sub import {
|
||||||
});
|
});
|
||||||
|
|
||||||
no strict 'refs';
|
no strict 'refs';
|
||||||
*{$caller . '::get'} = \&_get;
|
*{$super . '::get'} = \&_get;
|
||||||
*{$caller . '::set'} = \&_set;
|
*{$super . '::set'} = \&_set;
|
||||||
*{$caller . '::update'} = \&_update;
|
*{$super . '::update'} = \&_update;
|
||||||
*{$caller . '::instantiate'} = \&_instantiate;
|
*{$super . '::instantiate'} = \&_instantiate;
|
||||||
|
unshift @{$caller . '::ISA'}, $super;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub _install {
|
sub _install {
|
||||||
|
|
|
||||||
|
|
@ -55,10 +55,10 @@ my $written;
|
||||||
$written = 1;
|
$written = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub _set_a_property {
|
sub a_property {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $value = shift;
|
my $value = shift;
|
||||||
return "$value - BLAH";
|
return $self->next::method("$value - BLAH");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -85,7 +85,7 @@ is_deeply [ $subclass_object->getProperties ], ['property1', 'a_property', 'prop
|
||||||
|
|
||||||
is_deeply $object->get, { property1 => 'property 1 value' },
|
is_deeply $object->get, { property1 => 'property 1 value' },
|
||||||
'get returns hash with correct properties';
|
'get returns hash with correct properties';
|
||||||
is_deeply $subclass_object->get, { property1 => undef, a_property => undef, property2 => 'property 2 value' },
|
is_deeply $subclass_object->get, { property1 => undef, a_property => ' - BLAH', property2 => 'property 2 value' },
|
||||||
'get returns hash with correct properties';
|
'get returns hash with correct properties';
|
||||||
|
|
||||||
is_deeply $object->getProperty('property1'), { label => 'property1 label', defaultValue => $object },
|
is_deeply $object->getProperty('property1'), { label => 'property1 label', defaultValue => $object },
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue