我试图在Perl中使用多重继承,但我无法弄清楚如何从子构造函数中调用多个父构造函数。
A.pm:
package A;
use Carp qw (croak);
use strict;
use warnings;
sub new {
my $class = shift;
print "This is A new\n";
my $self->{DEV_TYPE} = shift || "A";
bless($self, $class);
return $self;
}
sub a_func{
print "This is A func\n";
}
1;
B.pm:
package B;
use Carp qw (croak);
use strict;
use warnings;
sub new {
my $class = shift;
print "This is B new\n";
my $self->{DEV_TYPE} = shift || "B";
bless($self, $class);
return $self;
}
sub b_func{
print "This is B func\n";
}
1;
C.pm:
package C;
use Carp qw (croak);
use strict;
use warnings;
eval "use A";
die $@ if $@;
eval "use B";
die $@ if $@;
our @ISA = ("A","B");
sub new {
my $class = shift;
my $self = $class->SUPER::new(@_);
print "This is C new\n";
$self->{DEV_TYPE} = shift || "C";
bless($self, $class);
return $self;
}
sub c_func{
print "This is C func\n";
}
1;
在C::new
中,$class->SUPER::new
没有为B调用构造函数。如果我使用$class->B::new(@_);
显式调用它,我会收到错误
无法通过包裹“B”在C.pm
找到对象方法“new”
我做错了什么?
答案 0 :(得分:7)
$class->SUPER::new
始终致电A::new
,因为A位于@ISA
中的B之前。请参阅perlobj中的method resolution order:
当一个类有多个父项时,方法查找顺序会变得更复杂。
默认情况下,Perl会对方法执行深度优先从左到右的搜索。这意味着它从
@ISA
数组中的第一个父项开始,然后搜索其所有父项,祖父母等。如果找不到该方法,则转到原始类中的下一个父项&#39 ; s@ISA
数组并从那里搜索。
这意味着$class->SUPER::new
只会调用其中一个父构造函数。如果您需要从子类运行两个父类中的初始化逻辑,请将其移动到this post中所述的单独方法中。
当您使用B::new
明确致电$class->B::new
时,您会获得
找不到对象方法" new"通过包" B"在C.pm
因为use B
正在加载core module B而不是您的模块。您应该重命名模块。
请注意,最好使用parent
pragma而不是手动设置@ISA
,例如
use parent qw(Parent1 Parent2);
parent
负责加载父模块,因此您可以删除关联的use
语句(顺便说一下,您不应该eval
。< / p>