Могут ли роли получать доступ к атрибутам ролей? - PullRequest
0 голосов
/ 12 января 2019

У меня есть класс, который выполняет роль, которая выполняет другую роль. Метод из класса может обращаться к атрибуту в роли верхнего уровня:

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;

Это даже не скомпилируется: SORRY Attribute $!x not declared in role B.

Может ли роль не видеть атрибуты в роли, которую она включает?

1 Ответ

0 голосов
/ 13 января 2019

Для этого необходимо ввести приватный метод в первой роли и получить доступ через него:

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 можно будет указать, как это работает. Пока что консервативно нет.

...