有谁知道为什么 TWEAK 例程在 BUILD 例程之前被命中?

Does anyone know why the TWEAK routine gets hit before the BUILD routine?

最少的代码:

 #!/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 月)。

向每个示例 class 添加 TWEAKBUILD 方法的快速实验表明调用顺序为 Widget::BUILD -> Widget::TWEAK -> File::BUILD -> File::TWEAK.

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

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

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

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

TWEAKBUILD 之后被调用。

不过,subclasses还是要按照他们parents classes的构造套路。考虑以下代码:

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

基本上,每个 class 的构造方法只有在 parent class 被调用后才会被调用,这意味着在构建和调整时你可以假设 parent class' 属性已正确初始化。

这其实就是那些方法需要是子方法的原因,否则,如果一个parent class的构建方法引用了私有属性,subclass继承parents 方法,你会得到一个错误,因为它将被专利和 child 调用,但 child 将无法访问。