Курс языка программирования 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 тест по содержанию этой темы.

Навигация по курсу

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


💪 Или перейдите сразу к упражнениям этого раздела.