为什么$ class-> SUPER :: new在使用多重继承时不调用所有父类的构造函数?

时间:2017-03-19 09:57:49

标签: perl multiple-inheritance

我试图在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”

我做错了什么?

1 个答案:

答案 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>