1Moose::Manual::Roles(3)User Contributed Perl DocumentatioMnoose::Manual::Roles(3)
2
3
4
6 Moose::Manual::Roles - Roles, an alternative to deep hierarchies and
7 base classes
8
10 version 2.2201
11
13 A role encapsulates some piece of behavior or state that can be shared
14 between classes. It is something that classes do. It is important to
15 understand that roles are not classes. You cannot inherit from a role,
16 and a role cannot be instantiated. We sometimes say that roles are
17 consumed, either by classes or other roles.
18
19 Instead, a role is composed into a class. In practical terms, this
20 means that all of the methods, method modifiers, and attributes defined
21 in a role are added directly to (we sometimes say "flattened into") the
22 class that consumes the role. These attributes and methods then appear
23 as if they were defined in the class itself. A subclass of the
24 consuming class will inherit all of these methods and attributes.
25
26 Moose roles are similar to mixins or interfaces in other languages and
27 are based on the original concept of Traits
28 <http://scg.unibe.ch/research/traits/> for the Smalltalk-80 dialect
29 Squeak.
30
31 Besides defining their own methods and attributes, roles can also
32 require that the consuming class define certain methods of its own. You
33 could have a role that consisted only of a list of required methods, in
34 which case the role would be very much like a Java interface.
35
36 Note that attribute accessors also count as methods for the purposes of
37 satisfying the requirements of a role.
38
40 Creating a role looks a lot like creating a Moose class:
41
42 package Breakable;
43
44 use Moose::Role;
45
46 has 'is_broken' => (
47 is => 'rw',
48 isa => 'Bool',
49 );
50
51 sub break {
52 my $self = shift;
53
54 print "I broke\n";
55
56 $self->is_broken(1);
57 }
58
59 Except for our use of Moose::Role, this looks just like a class
60 definition with Moose. However, this is not a class, and it cannot be
61 instantiated.
62
63 Instead, its attributes and methods will be composed into classes which
64 use the role:
65
66 package Car;
67
68 use Moose;
69
70 with 'Breakable';
71
72 has 'engine' => (
73 is => 'ro',
74 isa => 'Engine',
75 );
76
77 The "with" function composes roles into a class. Once that is done, the
78 "Car" class has an "is_broken" attribute and a "break" method. The
79 "Car" class also "does('Breakable')":
80
81 my $car = Car->new( engine => Engine->new );
82
83 print $car->is_broken ? 'Busted' : 'Still working';
84 $car->break;
85 print $car->is_broken ? 'Busted' : 'Still working';
86
87 $car->does('Breakable'); # true
88
89 This prints:
90
91 Still working
92 I broke
93 Busted
94
95 We could use this same role in a "Bone" class:
96
97 package Bone;
98
99 use Moose;
100
101 with 'Breakable';
102
103 has 'marrow' => (
104 is => 'ro',
105 isa => 'Marrow',
106 );
107
108 See also Moose::Cookbook::Roles::Comparable_CodeReuse for an example.
109
110 It's possible to compose existing roles into new roles. For example, we
111 can have a "HandleWithCare" class which applies both the "Breakable"
112 and "Package" roles to any class which consumes it:
113
114 package HandleWithCare;
115
116 use Moose::Role;
117
118 with 'Breakable', 'Package';
119
121 As mentioned previously, a role can require that consuming classes
122 provide one or more methods. Using our "Breakable" example, let's make
123 it require that consuming classes implement their own "break" methods:
124
125 package Breakable;
126
127 use Moose::Role;
128
129 requires 'break';
130
131 has 'is_broken' => (
132 is => 'rw',
133 isa => 'Bool',
134 );
135
136 after 'break' => sub {
137 my $self = shift;
138
139 $self->is_broken(1);
140 };
141
142 If we try to consume this role in a class that does not have a "break"
143 method, we will get an exception.
144
145 You can see that we added a method modifier on "break". We want classes
146 that consume this role to implement their own logic for breaking, but
147 we make sure that the "is_broken" attribute is always set to true when
148 "break" is called.
149
150 package Car
151
152 use Moose;
153
154 with 'Breakable';
155
156 has 'engine' => (
157 is => 'ro',
158 isa => 'Engine',
159 );
160
161 sub break {
162 my $self = shift;
163
164 if ( $self->is_moving ) {
165 $self->stop;
166 }
167 }
168
169 Roles Versus Abstract Base Classes
170 If you are familiar with the concept of abstract base classes in other
171 languages, you may be tempted to use roles in the same way.
172
173 You can define an "interface-only" role, one that contains just a list
174 of required methods.
175
176 However, any class which consumes this role must implement all of the
177 required methods, either directly or through inheritance from a parent.
178 You cannot delay the method requirement check so that they can be
179 implemented by future subclasses.
180
181 Because the role defines the required methods directly, adding a base
182 class to the mix would not achieve anything. We recommend that you
183 simply consume the interface role in each class which implements that
184 interface.
185
187 Roles are consumed using the "with" function.
188
189 Most of the time, you should only use one "with", even if you are
190 consuming multiple roles. If you consume roles using multiple "with"
191 statements Moose cannot detect method conflicts between those roles.
192
193 Roles can be consumed by classes or by other roles. When a class
194 consumes a role which in turn consumes other roles, the class gets all
195 of the roles applied at once.
196
197 Required Methods Provided by Attributes
198 As mentioned before, a role's required method may also be satisfied by
199 an attribute accessor. However, the call to "has" which defines an
200 attribute happens at runtime. This means that you must define the
201 attribute before consuming the role, or else the role will not see the
202 generated accessor. These attributes are Moose Attributes.
203
204 package Breakable;
205
206 use Moose::Role;
207
208 requires 'stress';
209
210 ########
211
212 package Car;
213
214 use Moose;
215
216 has 'stress' => (
217 is => 'ro',
218 isa => 'Int',
219 );
220
221 with 'Breakable';
222
223 In general, we recommend that you always consume roles after declaring
224 all your attributes.
225
226 It may also be the case that a class wants to consume two roles where
227 one role has an attribute providing a required method for another. For
228 example:
229
230 package Breakable;
231
232 use Moose::Role;
233
234 requires 'stress';
235
236 ########
237
238 package Stressable;
239
240 use Moose::Role;
241
242 has 'stress' => (
243 is => 'ro',
244 isa => 'Int',
245 );
246
247 ########
248
249 package Car;
250
251 use Moose;
252
253 # XXX - this will not work
254 with 'Breakable', 'Stressable';
255
256 However, this won't work. The problem is that the accessor methods
257 created for the "stress" attribute won't be present in the class when
258 the required method checks are done.
259
260 There are two possible workarounds. The recommended one is to use
261 "stub" subroutine(s) in the role providing the accessor(s):
262
263 package Stressable;
264
265 use Moose::Role;
266
267 sub stress;
268 has 'stress' => (
269 is => 'ro',
270 isa => 'Int',
271 );
272
273 The "sub stress;" line is called a "forward" declaration in the Perl
274 documentation. It creates what is called a "stub" subroutine, a
275 declaration without a body. This is good enough to satisfy the required
276 method checks done by Moose. The stub will not interfere with the
277 creation of a real subroutine later.
278
279 The other alternative is to use two separate calls to "with" in the
280 consuming class:
281
282 package Car;
283
284 use Moose;
285
286 # Not recommended
287 with 'Stressable';
288 with 'Breakable';
289
290 Each "with" is run as it is seen. The first call will consume just the
291 "Stressable" role, which will add the "stress" attribute to the "Car"
292 package, which in turn will create an accessor method named "stress".
293 Then when the "Breakable" role is consumed, the method it requires
294 already exists.
295
296 However, as mentioned earlier, multiple "with" declarations are not
297 recommended, because method conflicts between the roles cannot be seen.
298 In the example above, if both "Stressable" and "Breakable" contained
299 methods of the same name, what would happen is that the version in
300 "Stressable" would silently override the one in "Breakable".
301
303 Method modifiers and roles are a very powerful combination. Often, a
304 role will combine method modifiers and required methods. We already saw
305 one example with our "Breakable" example.
306
307 Method modifiers increase the complexity of roles, because they make
308 the role application order relevant. If a class uses multiple roles,
309 each of which modify the same method, those modifiers will be applied
310 in the same order as the roles are used:
311
312 package MovieCar;
313
314 use Moose;
315
316 extends 'Car';
317
318 with 'Breakable', 'ExplodesOnBreakage';
319
320 Assuming that the new "ExplodesOnBreakage" role also has an "after"
321 modifier on "break", the "after" modifiers will run one after the
322 other. The modifier from "Breakable" will run first, then the one from
323 "ExplodesOnBreakage".
324
326 If a class composes multiple roles, and those roles have methods of the
327 same name, we will have a conflict. In that case, the composing class
328 is required to provide its own method of the same name.
329
330 package Breakdancer;
331
332 use Moose::Role;
333
334 sub break {
335
336 }
337
338 If we compose both "Breakable" and "Breakdancer" in a class, we must
339 provide our own "break" method:
340
341 package FragileDancer;
342
343 use Moose;
344
345 with 'Breakable', 'Breakdancer';
346
347 sub break { ... }
348
349 A role can be a collection of other roles:
350
351 package Break::Bundle;
352
353 use Moose::Role;
354
355 with ('Breakable', 'Breakdancer');
356
357 When a role consumes another a role, the consuming role's methods
358 silently win in any conflict, and the consumed role's methods are
359 simply ignored.
360
362 If we want our "FragileDancer" class to be able to call the methods
363 from both its roles, we can alias the methods:
364
365 package FragileDancer;
366
367 use Moose;
368
369 with 'Breakable' => { -alias => { break => 'break_bone' } },
370 'Breakdancer' => { -alias => { break => 'break_dance' } };
371
372 However, aliasing a method simply makes a copy of the method with the
373 new name. We also need to exclude the original name:
374
375 with 'Breakable' => {
376 -alias => { break => 'break_bone' },
377 -excludes => 'break',
378 },
379 'Breakdancer' => {
380 -alias => { break => 'break_dance' },
381 -excludes => 'break',
382 };
383
384 The excludes parameter prevents the "break" method from being composed
385 into the "FragileDancer" class, so we don't have a conflict. This means
386 that "FragileDancer" does not need to implement its own "break" method.
387
388 This is useful, but it's worth noting that this breaks the contract
389 implicit in consuming a role. Our "FragileDancer" class does both the
390 "Breakable" and "BreakDancer", but does not provide a "break" method.
391 If some API expects an object that does one of those roles, it probably
392 expects it to implement that method.
393
394 In some use cases we might alias and exclude methods from roles, but
395 then provide a method of the same name in the class itself.
396
397 Also see Moose::Cookbook::Roles::Restartable_AdvancedComposition for an
398 example.
399
401 When a Moose role uses overloading, that overloading is composed into
402 any classes that consume the role. This includes the setting of the
403 "fallback" value for that role's overloading. Just as with methods and
404 attributes, when a role consumes another role, that other role's
405 overloading settings are applied to the role.
406
407 Just as with methods, there can be conflicts with overloading
408 implementations between multiple roles when they are all consumed by a
409 class. If two roles both provide different overloading implementations
410 for a given operator, that is a conflict. If two roles both implement
411 overloading and have different "fallback" values, that is also
412 considered a conflict. These conflicts are detected when multiple roles
413 are being composed into a class together.
414
415 When a role consumes another role, the consuming role's overloading
416 fallback and operator implementations silently "win" the conflict.
417
419 A role can say that it cannot be combined with some other role. This
420 should be used with great caution, since it limits the re-usability of
421 the role.
422
423 package Breakable;
424
425 use Moose::Role;
426
427 excludes 'BreakDancer';
428
430 You may want to add a role to an object instance, rather than to a
431 class. For example, you may want to add debug tracing to one instance
432 of an object while debugging a particular bug. Another use case might
433 be to dynamically change objects based on a user's configuration, as a
434 plugin system.
435
436 The best way to do this is to use the "apply_all_roles()" function from
437 Moose::Util:
438
439 use Moose::Util qw( apply_all_roles );
440
441 my $car = Car->new;
442 apply_all_roles( $car, 'Breakable' );
443
444 This function can apply more than one role at a time, and will do so
445 using the normal Moose role combination system. We recommend using this
446 function to apply roles to an object. This is what Moose uses
447 internally when you call "with".
448
449 Handling required attributes for roles.
450 Application of some roles will require additional parameters being
451 specified to satisfy them, for example:
452
453 {
454 package Car;
455 use Moose;
456 }
457 {
458 package Breakable;
459 use Moose::Role;
460
461 has 'breakable_parts' => ( is => 'ro', required => 1 );
462 }
463
464 my $car = Car->new;
465
466 # next line dies with: Attribute (breakable_parts) is required
467 apply_all_roles( $car, 'Breakable' );
468
469 This will require passing the additional parameters at application time
470 as follows:
471
472 apply_all_roles( $car, 'Breakable' => {
473 rebless_params => {
474 # Parameters to 'Breakable'
475 breakable_parts => [qw( tires wheels windscreen )],
476 }
477 });
478
479 Obviously, this interface is better simplified as a method on "Car":
480
481 sub make_breakable {
482 my ( $self, %params ) = @_;
483 apply_all_roles($self, 'Breakable', { rebless_params => \%params });
484 }
485
486 my $car = Car->new();
487 $car->make_breakable( breakable_parts => [qw( tires wheels windscreen )] );
488
490 • Stevan Little <stevan@cpan.org>
491
492 • Dave Rolsky <autarch@urth.org>
493
494 • Jesse Luehrs <doy@cpan.org>
495
496 • Shawn M Moore <sartak@cpan.org>
497
498 • יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
499
500 • Karen Etheridge <ether@cpan.org>
501
502 • Florian Ragwitz <rafl@debian.org>
503
504 • Hans Dieter Pearcey <hdp@cpan.org>
505
506 • Chris Prather <chris@prather.org>
507
508 • Matt S Trout <mstrout@cpan.org>
509
511 This software is copyright (c) 2006 by Infinity Interactive, Inc.
512
513 This is free software; you can redistribute it and/or modify it under
514 the same terms as the Perl 5 programming language system itself.
515
516
517
518perl v5.34.0 2022-01-21 Moose::Manual::Roles(3)