为什么子类调用它的父类函数以及它们自己的函数?

发布于 2024-12-11 09:30:14 字数 1559 浏览 0 评论 0原文

我开始掌握 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

现在实例化 调试输出,

my $child = ChildClass->new();

根据我的

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

new() 生成的调用顺序对我来说是这样的,我发现它们都调用 BUILD a la Moose。美好的。我想我误解了为什么在这种情况下baseClass不调用它自己的baseClass::init,或者为什么childClass不只调用它自己的childClass::BUILD。

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

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

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...哈哈

I started getting the hang of inheritance in Perl/Moose, but I'm starting to run into some rough spots.

For example, the build order of inherited objects seems to make sense, but inheritance doesn't seem to work how I expect--

If my baseClass calls BUILD all subClasses will call their BUILD as well as the baseClass' BUILD, but this isnt limited to the moosey BUILD function.

If I define a function init() in the baseClass, and call itfrom the baseClass BUILD, the subClasses init() gets called instead of the baseClass' init()

o_O

Assume for brevity sake that we have the follow object constructs:

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

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

Now instantiate the childClass

my $child = ChildClass->new();

The resulting call order from new() looks like this to me based on my debug output

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

I get that they both call BUILD a la Moose. Fine. I guess I'm misunderstanding why baseClass doesn't call it's own baseClass::init in this case, or alternatively why childClass doesnt just call its own childClass::BUILD.

Do I need to specifically "override" these functions with the Moose "override" function modifier?

Then if i throw BUILDARGS in the mix, it gets even more fun, because the question is who gets the arguments passed into new() and what if the baseClass has roles associated with it?

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');

then

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

Which is $class in this case??

Don't tell me I have to override BUILDARGS... lol

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

你是年少的欢喜 2024-12-18 09:30:14

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

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

Moose 对待 BUILD 的方式与 Perl 通常对待方法调用的方式不同。当您在 BUILD 方法中调用 init 时,Perl 将使用其正常方法解析并查找子级的 init 方法,因为它掩盖了父级的 init 方法。然后子方法可以使用 $self->SUPER::init() 调用父方法,Moose 的 'override' 修饰符和 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();
    ...
}

I'm assuming you have a BUILD function in each class a bit like

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

Moose treats BUILD differently that Perl normally treats method calls. When you call init in your BUILD methods Perl will use it's normal method resolution and find the child's init method as it masks the parent's init method. The child's method can then call the parents with $self->SUPER::init(), Moose's 'override' modifier and super() is just modified way to use SUPER::.

If you only call init in your parent class's BUILD method you can use any of the standard Moose method modifiers like 'before', 'after', 'around', or 'override' to control when the child class's init is called relative to the parent's init.

If on the other hand you want each class's init to be called when that class's build is run you can specifically ask Perl to skip the standard method lookup and use a specified class's method:

package ParentClass;

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

package ChildClass;

sub BUILD {
    my $self = shift;
    ...
    $self->ChildClass::init();
    ...
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文