【问题标题】:Why does a childClass call its parentClass functions as well as their own?为什么 childClass 调用它的 parentClass 函数以及它们自己的函数?
【发布时间】:2011-10-21 18:55:29
【问题描述】:

我开始在 Perl/Moose 中掌握继承的窍门,但我开始遇到一些困难。

例如,继承对象的构建顺序似乎是有道理的,但继承似乎并没有按我的预期工作--

如果我的基类调用 BUILD,所有子类都将调用它们的 BUILD 以及基类的 BUILD,但这不限于 moosey BUILD 函数。

如果我在基类中定义一个函数 init(),并从基类 BUILD 中调用它,则调用子类 init() 而不是基类的 init()

o_O

为简洁起见,假设我们有以下对象构造:

BaseClass
    ::BUILD --> call init()
    ::init  --> do BaseStuff 

ChildClass extends BaseClass
    ::BUILD --> call init()
    ::init  --> do ChildStuff

现在实例化 childClass

my $child = ChildClass->new();

根据我的调试输出,从 new() 得到的调用顺序在我看来是这样的

BaseClass->BUILD()
BaseClass->init() <--- this calls ChildClass::init
ChildClass->BUILD()
ChildClass->init() <--- this calls ChildClass::init too!

我知道他们都称 BUILD a la Moose。美好的。我想我误解了为什么在这种情况下 baseClass 不调用它自己的 baseClass::init,或者为什么 childClass 不只是调用它自己的 childClass::BUILD。

我是否需要使用 Moose“覆盖”函数修饰符专门“覆盖”这些函数?

然后,如果我将 BUILDARGS 加入其中,它会变得更加有趣,因为问题是谁将参数传递给 new() 以及如果 baseClass 具有与之关联的角色怎么办?

BaseClass (has role CanSee and has seesWith() attribute)
BaseClass (has role NameTag and has name() attribute)
ChildClass (has role FavoriteColor and has color() attribute)

my $child = ChildClass->new( name => 'Jane', seesWith => 'eyes', color => 'red');

然后

ChildClass
        ::BUILDARGS --> 
             ($orig,$class,$args) = @_;
             return $class->$orig(@_);

在这种情况下 $class 是什么?

别告诉我我必须重写 BUILDARGS...大声笑

【问题讨论】:

    标签: perl oop inheritance instantiation overriding


    【解决方案1】:

    我假设你在每个类中都有一个 BUILD 函数,有点像

    sub BUILD {
        my $self = shift;
        ...
        $self->init();
        ...
    }
    

    Moose 对待 BUILD 的方式与 Perl 通常对待方法调用的方式不同。当您在 BUILD 方法中调用 init 时,Perl 将使用它的正常方法解析并找到子级的 init 方法,因为它掩盖了父级的 init 方法。然后,孩子的方法可以使用 $self-&gt;SUPER::init() 调用父母,Moose 的“覆盖”修饰符和 super() 只是修改为使用 SUPER:: 的方式。

    如果您只在父类的 BUILD 方法中调用 init,您可以使用任何标准 Moose 方法修饰符,例如“before”、“after”、“around”或“override”来控制何时调用子类的 init相对于父级的初始化。

    另一方面,如果您希望在运行该类的构建时调用每个类的 init,您可以明确要求 Perl 跳过标准方法查找并使用指定类的方法:

    package ParentClass;
    
    sub BUILD {
        my $self = shift;
        ...
        $self->ParentClass::init();
        ...
    }
    
    package ChildClass;
    
    sub BUILD {
        my $self = shift;
        ...
        $self->ChildClass::init();
        ...
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-12-06
      • 2016-03-15
      • 1970-01-01
      • 1970-01-01
      • 2011-08-03
      • 1970-01-01
      • 2021-12-07
      相关资源
      最近更新 更多