8

最小代码:

 #!/usr/bin/raku

 class   Widget {
         submethod TWEAK(:$content, :$styles) {
                 say "t1\n";
         }
 }

 class   File is Widget {
         submethod BUILD() {
                 say "b1";
         }
 }

 my $xml = File.new();

和输出:

 t1

 b1

相关文档位于https://docs.raku.org/language/objects#Object_construction。我引用:“在调用 BUILD 方法之后,调用名为 TWEAK 的方法(如果它们存在),再次使用传递给 new 的所有命名参数”。

我正在使用 Fedora 32 附带的 rakudo 版本(rakudo-0.2020.02-1.fc32.x86_64 所以可能是今年 2 月)。

4

2 回答 2

7

一个快速的实验将一个TWEAKandBUILD方法添加到每个缺少它们的示例类中,显示调用的顺序是Widget::BUILD-> Widget::TWEAK-> File::BUILD-> File::TWEAK

所以我认为问题在于文档的措辞“在调用 BUILD 方法后,如果存在名为 TWEAK 的方法,则再次调用所有已传递给 new 的命名参数。”

我认为这可能应该是“在为每个类调用 BUILD 方法之后,为该类调用名为 TWEAK 的方法,如果它们存在,再次使用传递给 new 的所有命名参数。”

然后,这将记录似乎正在发生的事情。

注意:自回答此问题以来,文档已更新以反映代码的运行方式。

于 2020-09-28T14:10:55.960 回答
4

TWEAK之后调用BUILD

但是,子类仍然需要遵循其父类的构建例程。考虑以下代码:

class Foo {
  submethod TWEAK { say "Foo tweak" }
  submethod BUILD { say "Foo build" }
}

class Bar is Foo {
  submethod TWEAK { say "Bar tweak" }
  submethod BUILD { say "Bar build" }
}

Bar.new

如果你运行它,你可以很快看到发生了什么:

Foo build
Foo tweak
Bar build
Bar tweak

基本上,每个类的构造方法在为父类调用之前不会被调用,这意味着在构建和调整时,您可以假设父类的属性已正确初始化。

这实际上是这些方法需要子方法的原因,否则,如果父类的构建方法引用了私有属性,并且子类继承了父方法,则会出现错误,因为它将同时为专利和子调用,但孩子将无法访问。

于 2020-09-28T14:44:13.840 回答