package a::b::c:d
my $res = a::b::c:e->new(); # i am doing like this
# is there any othere to do this
sub new {
...
my $self = {
#result = a::b::c:e->new();
}
}
sub test {
}
sub test2 {
}
1;
package a::b::c:e
sub new {
...
}
sub testresult {
}
1;
我的问题是:
如何在新版本中初始化e
中的d
模块,而不是创建每个函数,
如何使用它将一些结果存储到e:testresult
答案 0 :(得分:2)
有两种策略 - 检查符号表以在创建时初始化,或者使用AUTOLOAD并使用can
进行测试。 AUTOLOAD可能比较麻烦,因为你必须处理方法不存在的情况:
sub AUTOLOAD {
my $self = shift;
my $method = $AUTOLOAD;
$method =~ s/.*://; # strip package name
if ( $self->{'result'}->can($method) ) {
return $self->{'result'}->$method(@_);
} else {
croak "Unknown method : $method";
}
}
但符号表技巧很脆弱,好像他们正在使用继承,你也不会看到继承的方法而没有走上@ISA。 (即使他们不是 - 他们可能会在未来开始使用继承,这会导致事情破裂)
...
通常,当您尝试复制其他模块的界面时,您有一个继承案例,因此您可能想问自己::d
和::e
之间的关系:< / p>
a::b::c::d
是a::b::c::e
a::b::c::d
使用a::b::c::e
如果它是一个is-a关系,它通常更适合继承(尽管你可能有每个方法的包装器,但仍然需要完成整个练习)。如果它是一个使用关系,你可能不希望从它们拥有的每一个方法继承,并且只能对列表进行硬编码(尽管如果使用的类被更新,列表可能会改变)
foreach my $method ( @list_of_methods_to_copy ) {
*{$method} = sub {
my $self = shift;
return $self->{'results'}->$method(@_);
}
}
答案 1 :(得分:0)
如果您没有在两个类之间寻找继承,那么在我看来您可能希望使用Class::Delegator
来编写您的类。这样,您可以通过在a::b::c::d
中添加以下内容来创建委派例程。
use Class::Delegator send => 'testresult', to => '{result}';
但是你还需要修复你的构造函数:
my $self
= bless {
result => a::b::c::e->new()
}, $class_name
;
return $self;
完成后,您将有一个字段'{result}'委托给。