角色可以访问包含的角色属性吗?

时间:2019-01-12 14:58:07

标签: perl6

我有一个扮演另一个角色的类。类中的方法可以访问顶级角色中的属性:

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​​}}。

角色不能看到其包含的角色中的属性吗?

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语言版本可能会指定一种解决方法。就目前而言,保守地说还不是。