这是我们目前的实施:
我们有一个基类 - Coew Device。有许多类继承自此Core Device类 - 已实现特定功能。这些派生类是其他类型设备的基类。简单来说,它就像以下结构:
核心设备 - > LevelA设备==> LevelB设备.... ==> Z级设备
要处理这些叶级设备,最终应用程序会创建此设备的对象,并开始调用从设备级别Z到根目录的API。
e.g。
my $iPhone = new DeviceLevelZ (NAME => 'iPhone');
目前,为了处理未在任何树路径中实现的sub,AUTOLOAD用于Core Device基类。因此,基类的AUTOLOAD - 核心设备 - 根据从最终应用程序调用的子进行必要的操作。
现在,我们计划远离AUTOLOAD,并希望使用Conway的Class :: Delegation模块来使用该代表团。
为了实现这一点,我通过定义像这样的委托
更新了核心设备基类use Class::Delegation
send => 'getFoo',
to => sub { print "Hello Worlld!! I am foo\n" },
;
但是当我从设备对象调用sub getFoo时,它没有委托给这个delagtor。
这是一个提及相同行为的小程序:
my $device = new DeviceLevelZ();
$device->get();
$device->getDelegation();
package ResourceX;
use Class::Delegation
send => 'getDelegation',
to => sub { print "Hello Worlld!! I am foo\n" },
;
sub new
{
my ($class, %args) = @_;
my $self = {};
bless $self, $class;
return $self;
}
sub get
{
print "I am a resource\n";
}
package DeviceLevelZ;
use base qw(ResourceX);
sub new
{
my ($class, %args) = @_;
my $self = $class->SUPER::new(%args);
bless $self, $class;
return $self;
}
1;
答案 0 :(得分:4)
它正在尝试委派,但您要发回print
的结果。由于1
没有受到祝福,因此您无法在其上调用方法,并且授权在此时失败。
我认为您错过了为委派点指定sub
的意义。它应该返回代表。达米安sez:
子程序也可以返回对象的引用,在这种情况下,子程序被委托给该对象(而不是当前对象的属性)。当实际委派目标比直接属性更强复杂时,这可能很有用。 [强调我的]
因此,如果您在代码中添加这样的包:
package DoesDelegation;
our $Delegate = bless {}, __PACKAGE__;
sub getDelegation {
say 'You just called me!';
}
你可以像这样修改委托子:
...
to => sub {
print "Hello Worlld!! I am foo\n";
$DoesDelegation::Delegate;
},
你不会看到失败的委托 - 因为现在你已经传回了可以处理消息'getDelegation'的东西
另外,为了让您了解后台发生的事情:如果您修改代码如下:
use Class::Delegation
send => 'getDelegation',
to => sub {
use Data::Dumper;
warn "In delegate \@_ :\n", Dumper( \@_ ), "\n";
warn "\$1='$1'\n\$2='$2'\n";
print "Hello Worlld!! I am foo\n";
$DoesDelegation::Delegate;
},
你会看到:
In delegate @_ :
$VAR1 = [
bless( {}, 'DeviceLevelZ' ),
'getDelegation'
];
$1='DeviceLevelZ::'
$2='getDelegation'
因此有两个数据来源。在@_
中,您获得1)公共对象和2)方法的名称。然而,您在$1
和$2
中获得了其他数据,这是按包(存储名称?)和名称拆分的方法的全名。
Class::Delegator
如果你有一个复杂的代表团,那么你可以使用一个sub。但我在你的描述中没有看到。如果你没有有一些复杂的东西,那么我推荐David Wheeler的精简版Class::Delegator
,我在这里得到了Conway的模块,我认为这是真的:
达米安康威的精彩模块比这个模块做了十倍 - 并且速度慢了十倍。
我还建议您使用use
语句的声明性结构来分派您的代理,而不是尝试委托给将其路由到正确的委托的子,就像您在此处所做的那样。
如果您有代表处理getFoo
,那么请执行此操作:
...
send => 'getFoo', to => '{foo_getter}'
第三种也是最后一种方法,Moose
Delegation:
package Website;
use Moose;
has 'uri' => (
is => 'ro',
isa => 'URI',
handles => [qw( host path )],
);
因此,在指定聚合对象的委托时,可以在handles
参数中指定委托。