为什么“BUILD”看不到父类的属性?

Paw*_*bkr 11 raku

class A { has $.name; };
class B is A { submethod BUILD { $!name = 'foo' } };
Run Code Online (Sandbox Code Playgroud)

这段代码看起来很自然,但会抛出错误。

Attribute $!name not declared in class B
Run Code Online (Sandbox Code Playgroud)

是的,它没有在 class 中声明B,但我们在部分构造的对象中B::BUILD,并且文档说bless creates the new object, and then walks all subclasses in reverse method resolution order。所以在这个阶段,类的$!name属性应该是已知的B,对吧?

有没有办法在对象构造过程中设置父类属性而不使用new方法?我知道这new可以解决问题,但是BUILD有很多语法糖和BUILD/TWEAK感觉比解析 中的低级blessing更 DWIMy 和直接new

Eli*_*sen 5

私有属性语法 ($!foo) 仅适用于词法可见的属性。这就是为什么它们是私有的:-)

如果class A希望其他类能够更改,则需要显式或隐式(使用is rw)提供一个 mutator 方法。

或者,您可以让 A 类信任 B 类,如https://docs.raku.org/routine/trusts#(Type_system)_trait_trusts中所述。

尽管如此,我还是觉得使用角色会做得更好:

role A {
    has $.name is rw;
}
class B does A {
    submethod BUILD { $!name = 'foo' }
}
Run Code Online (Sandbox Code Playgroud)