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

前端之家收集整理的这篇文章主要介绍了perl – 为什么$class-> SUPER :: new在使用多重继承时不调用所有父类的构造函数?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我试图在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(@_);显式调用它,我得到错误

Can’t locate object method “new” via package “B” at C.pm

我究竟做错了什么?

解决方法

$class-> SUPER :: new总是调用A :: new,因为A在@ISA中位于B之前.请参阅perlobj中的 method resolution order

When a class has multiple parents,the method lookup order becomes more complicated.

By default,Perl does a depth-first left-to-right search for a method. That means it starts with the first parent in the @ISA array,and then searches all of its parents,grandparents,etc. If it fails to find the method,it then goes to the next parent in the original class’s @ISA array and searches from there.

这意味着$class-> SUPER :: new只会调用其中一个父构造函数.如果您需要从子类运行两个父类中的初始化逻辑,请将其移动到单独的方法中,如this post中所述.

当您使用$class-> B :: new显式调用B :: new时,您会得到

Can’t locate object method “new” via package “B” at C.pm

因为使用B正在加载core module B而不是你的模块.您应该重命名您的模块.

请注意,最好使用parent编译指示而不是手动设置@ISA,例如

use parent qw(Parent1 Parent2);

parent负责加载父模块,因此你可以删除相关的use语句(顺便说一下,你不应该使用它来进行评估).

猜你在找的Perl相关文章