Для этого необходимо ввести приватный метод в первой роли и получить доступ через него:
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 можно будет указать, как это работает. Пока что консервативно нет.