我有一个扮演另一个角色的类。类中的方法可以访问顶级角色中的属性:
role A {
has $.x
}
role B does A {
}
class C does B {
method this() { say $!x }
}
C.new(:x(1)).this;
那很好,可以说1,就像我认为的那样。
但是我有许多类都扮演角色B,我想共享方法this(),所以我将其上移到角色B:
role A {
has $.x
}
role B does A {
method this() { $!x }
}
class C does B {}
C.new(:x(1)).this;
它甚至不会编译:{{1}}。
角色不能看到其包含的角色中的属性吗?
答案 0 :(得分:7)
要做到这一点,需要在第一个角色中引入一个私有方法,并通过该方法进行访问:
role A {
has $.x;
method !x() { $!x }
}
role B does A {
method this() { self!x }
}
class C does B {}
say C.new(:x(1)).this; # 1
原始代码不起作用的原因-角色是通用的并且可能因不同类型的参数集而重载,因此提及角色本身就是通用的。因此,通常does A
不能确定特定的目标角色;它们可能有多个,并且它们可能具有不同的属性。直到我们将角色组合到一个类中之后,我们才最终确定所组成的具体角色集。
但是,属性访问是一种变量访问,因此我们在编译角色时进行了检查。在最后一堂课中,这并不是什么大问题,因为到那时我们将选择我们将使用的所有具体角色。这就是为什么它可以轻松地在那里工作的原因。对于role
情况,我们直到组成最终类的时候才真正检查它们,它们可能完全在单独的编译单元中。这可能是一个可解决的问题,将来的Perl 6语言版本可能会指定一种解决方法。就目前而言,保守地说还不是。