Objects · lesson 14 of 18
Roles
Package behaviour in roles and compose it into classes with does.
A role is a bundle of methods a class can compose in with does — Raku's answer to "I want to share behaviour without inheritance":
role Greeter {
method greet() { "Hi, I am { self.name }." }
}
class Robot does Greeter {
has $.name;
}
class Human does Greeter {
has $.name;
}
say Robot.new(name => 'R2-D2').greet;
say Human.new(name => 'Ada').greet;
Output
Hi, I am R2-D2.
Hi, I am Ada.The role calls self.name and trusts whatever class it lands in to provide it.
Composing several roles #
A class can do any number of roles, and roles can carry attributes too:
role CanFly {
method fly() { "{ self.name } takes off!" }
}
role CanSwim {
method swim() { "{ self.name } dives in!" }
}
class Duck does CanFly does CanSwim {
has $.name;
}
my $d = Duck.new(name => 'Donald');
say $d.fly;
say $d.swim;
Output
Donald takes off!
Donald dives in!Checking for a role #
The .does method asks any object whether it plays a role:
role Loud { }
class Drum does Loud { }
class Flute { }
say Drum.new.does(Loud);
say Flute.new.does(Loud);
Output
True
FalseTry it #
Add a Shouter role with a shout method that returns the object's name uppercased, with a ! at the end.
role Shouter {
}
class Coach does Shouter {
has $.name;
}
say Coach.new(name => 'Bob').shout;
Show a solution
role Shouter {
method shout() { self.name.uc ~ '!' }
}
class Coach does Shouter {
has $.name;
}
say Coach.new(name => 'Bob').shout;
Output
BOB!