Course of Raku / Objects, I/O, and exceptions / Classes and objects / Roles
Adding a role to an object
A role does not have to be baked into a class. You can also give one
to an object that already exists, using the but operator.
It mixes the role into a single object at run time and returns a new
object that plays the role:
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; # HELLOOnly $loud gained the role. The Greeter
class and every other Greeter object are untouched, so
$quiet still greets in the ordinary way. When the role and
the class both define a method with the same name, the role’s version
wins, and callsame calls the one it overrode — here the
original greet from Greeter, whose result is
then upper-cased.
An object that has a role mixed in is recognised as doing that role:
say $quiet ~~ Loud; # False
say $loud ~~ Loud; # Truebut leaves the original object as it was and hands you a
new one. If you would rather change an existing object in place, use the
does operator instead:
my $speaker = Greeter.new;
$speaker does Loud;
say $speaker.greet; # HELLOMixing roles into individual objects lets you decide, one object at a time, which extra behaviour it should take on — without defining a separate class for every combination.
Practice
Complete the quiz that covers the contents of this topic.
Course navigation
← Composing several roles | Quiz — Roles →
💪 Or jump directly to the
exercises in this section.