Курс Raku / Об’єкти, введення-виведення та винятки / Класи та об’єкти / Ролі

Додавання ролі об’єкту

Роль не обов’язково вбудовувати в клас. Її можна надати й об’єктові, який уже існує, за допомогою оператора but. Він підмішує роль в один об’єкт під час виконання й повертає новий об’єкт, що цю роль виконує:

role Loud {
    method greet {
        callsame().uc;
    }
}

class Greeter {
    method greet {
        'Hello';
    }
}

my $quiet = Greeter.new;
my $loud  = Greeter.new but Loud;

say $quiet.greet; # Hello
say $loud.greet;  # HELLO

Роль отримав лише $loud. Клас Greeter і кожен інший об’єкт Greeter лишилися недоторканими, тож $quiet і далі вітається у звичайний спосіб. Коли і роль, і клас визначають метод з однаковим іменем, перемагає версія ролі, а callsame викликає ту, яку вона перекрила, — тут початковий greet із Greeter, чий результат потім переводять у верхній регістр.

Об’єкт, у який підмішано роль, розпізнається як такий, що її виконує:

say $quiet ~~ Loud; # False
say $loud  ~~ Loud; # True

but лишає початковий об’єкт таким, яким він був, і віддає вам новий. Якщо ви радше хочете змінити наявний об’єкт на місці, скористайтеся натомість оператором does:

my $speaker = Greeter.new;
$speaker does Loud;
say $speaker.greet; # HELLO

Підмішування ролей в окремі об’єкти дозволяє вирішувати для кожного об’єкта зокрема, якої додаткової поведінки він має набути, — не визначаючи окремого класу для кожного поєднання.

Практика

Виконайте 1 тест за змістом цієї теми.

Навігація курсом

Композиція кількох ролей   |   Тест — Ролі


💪 Або перейдіть одразу до вправ цього розділу.