我开始在Perl / Moose中获得继承权,但我开始遇到一些粗糙的问题。
例如,继承对象的构建顺序似乎有意义,但继承似乎并不像我期望的那样 -
如果我的baseClass调用BUILD,所有子类将调用它们的BUILD以及baseClass的BUILD,但这不仅限于moosey BUILD函数。
如果我在baseClass中定义一个函数init(),并从baseClass BUILD调用它,则调用子类init()而不是baseClass的'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 ... lol
答案 0 :(得分:3)
我假设你在每个类中都有一个BUILD函数,有点像
sub BUILD {
my $self = shift;
...
$self->init();
...
}
Moose以不同的方式处理BUILD,Perl通常会处理方法调用。当您在BUILD方法中调用init时,Perl将使用它的正常方法解析并找到子进程的init方法,因为它掩盖了父进程的init方法。然后,孩子的方法可以使用$self->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();
...
}