Commit | Line | Data |
ef45e915 |
1 | =pod |
2 | |
3 | =head1 NAME |
4 | |
d67ce58f |
5 | Moose::Manual::Roles - Roles, an alternative to deep hierarchies and base classes |
ef45e915 |
6 | |
7 | =head1 WHAT IS A ROLE? |
8 | |
9 | A role is something that classes do. Usually, a role encapsulates some |
10 | piece of behavior or state that can be shared between classes. It is |
c89a5d69 |
11 | important to understand that I<roles are not classes>. You cannot |
12 | inherit from a role, and a role cannot be instantiated. We sometimes |
13 | say that roles are I<consumed>, either by classes or other roles. |
ef45e915 |
14 | |
15 | Instead, a role is I<composed> into a class. In practical terms, this |
16 | means that all of the methods and attributes defined in a role are |
ca426a3a |
17 | added directly to (we sometimes say "flattened into") the class that |
18 | consumes the role. These attributes and methods then appear as if they |
c89a5d69 |
19 | were defined in the class itself. A subclass of the consuming class |
20 | will inherit all of these methods and attributes. |
ef45e915 |
21 | |
22 | Moose roles are similar to mixins or interfaces in other languages. |
23 | |
24 | Besides defining their own methods and attributes, roles can also |
25 | require that the consuming class define certain methods of its |
26 | own. You could have a role that consisted only of a list of required |
27 | methods, in which case the role would be very much like a Java |
28 | interface. |
29 | |
30 | =head1 A SIMPLE ROLE |
31 | |
32 | Creating a role looks a lot like creating a Moose class: |
33 | |
34 | package Breakable; |
35 | |
36 | use Moose::Role; |
37 | |
38 | has 'is_broken' => ( |
39 | is => 'rw', |
40 | isa => 'Bool', |
41 | ); |
42 | |
43 | sub break { |
44 | my $self = shift; |
45 | |
46 | print "I broke\n"; |
47 | |
48 | $self->is_broken(1); |
49 | } |
50 | |
0c39debe |
51 | Except for our use of L<Moose::Role>, this looks just like a class |
ef45e915 |
52 | definition with Moose. However, this is not a class, and it cannot be |
53 | instantiated. |
54 | |
55 | Instead, its attributes and methods will be composed into classes |
56 | which use the role: |
57 | |
58 | package Car; |
59 | |
60 | use Moose; |
61 | |
62 | with 'Breakable'; |
63 | |
64 | has 'engine' => ( |
65 | is => 'ro', |
66 | isa => 'Engine', |
67 | ); |
68 | |
69 | The C<with> function composes roles into a class. Once that is done, |
70 | the C<Car> class has an C<is_broken> attribute and a C<break> |
71 | method. The C<Car> class also C<does('Breakable')>: |
72 | |
c56e5db4 |
73 | my $car = Car->new( engine => Engine->new ); |
ef45e915 |
74 | |
c56e5db4 |
75 | print $car->is_broken ? 'Still working' : 'Busted'; |
76 | $car->break; |
77 | print $car->is_broken ? 'Still working' : 'Busted'; |
ef45e915 |
78 | |
79 | $car->does('Breakable'); # true |
80 | |
81 | This prints: |
82 | |
83 | Still working |
84 | I broke |
85 | Busted |
86 | |
87 | We could use this same role in a C<Bone> class: |
88 | |
89 | package Bone; |
90 | |
91 | use Moose; |
92 | |
93 | with 'Breakable'; |
94 | |
95 | has 'marrow' => ( |
96 | is => 'ro', |
97 | isa => 'Marrow', |
98 | ); |
99 | |
100 | =head1 REQUIRED METHODS |
101 | |
102 | As mentioned previously, a role can require that consuming classes |
103 | provide one or more methods. Using our C<Breakable> example, let's |
104 | make it require that consuming classes implement their own C<break> |
105 | methods: |
106 | |
107 | package Breakable; |
108 | |
109 | use Moose::Role; |
110 | |
111 | requires 'break'; |
112 | |
113 | has 'is_broken' => ( |
114 | is => 'rw', |
115 | isa => 'Bool', |
116 | ); |
117 | |
118 | after 'break' => sub { |
119 | my $self = shift; |
120 | |
121 | $self->is_broken(1); |
c56e5db4 |
122 | }; |
ef45e915 |
123 | |
124 | If we try to consume this role in a class that does not have a |
125 | C<break> method, we will get an exception. |
126 | |
ca426a3a |
127 | You can see that we added a method modifier on C<break>. We want |
128 | classes that consume this role to implement their own logic for |
129 | breaking, but we make sure that the C<is_broken> attribute is always |
130 | set to true when C<break> is called. |
ef45e915 |
131 | |
132 | package Car |
133 | |
ca426a3a |
134 | use Moose; |
ef45e915 |
135 | |
136 | with 'Breakable'; |
137 | |
138 | has 'engine' => ( |
139 | is => 'ro', |
140 | isa => 'Engine', |
141 | ); |
142 | |
143 | sub break { |
144 | my $self = shift; |
145 | |
c56e5db4 |
146 | if ( $self->is_moving ) { |
147 | $self->stop; |
ef45e915 |
148 | } |
149 | } |
150 | |
c89a5d69 |
151 | =head2 Roles Versus Abstract Base Classes |
152 | |
153 | If you are familiar with the concept of abstract base classes in other |
154 | languages, you may be tempted to use roles in the same way. |
155 | |
398e8913 |
156 | You I<can> define an "interface-only" role, one that contains I<just> |
157 | a list of required methods. |
c89a5d69 |
158 | |
159 | However, any class which consumes this role must implement all of the |
160 | required methods, either directly or through inheritance from a |
161 | parent. You cannot delay the method requirement check so that they can |
162 | be implemented by future subclasses. |
163 | |
164 | Because the role defines the required methods directly, adding a base |
165 | class to the mix would not achieve anything. We recommend that you |
166 | simply consume the interface role in each class which implements that |
167 | interface. |
168 | |
ef45e915 |
169 | =head1 USING METHOD MODIFIERS |
170 | |
171 | Method modifiers and roles are a very powerful combination. Often, a |
172 | role will combine method modifiers and required methods. We already |
173 | saw one example with our C<Breakable> example. |
174 | |
eb169874 |
175 | Method modifiers increase the complexity of roles, because they make |
c56e5db4 |
176 | the role application order relevant. If a class uses multiple roles, |
177 | each of which modify the same method, those modifiers will be applied |
178 | in the same order as the roles are used: |
eb169874 |
179 | |
180 | package MovieCar; |
181 | |
182 | use Moose; |
183 | |
184 | extends 'Car'; |
185 | |
186 | with 'Breakable', 'ExplodesOnBreakage'; |
187 | |
188 | Assuming that the new C<ExplodesOnBreakage> method I<also> has an |
189 | C<after> modifier on C<break>, the C<after> modifiers will run one |
190 | after the other. The modifier from C<Breakable> will run first, then |
191 | the one from C<ExplodesOnBreakage>. |
192 | |
193 | =head1 METHOD CONFLICTS |
194 | |
195 | If a class composes multiple roles, and those roles have methods of |
196 | the same name, we will have a conflict. In that case, the composing |
197 | class is required to provide its I<own> method of the same name. |
198 | |
dab94063 |
199 | package Breakdancer; |
eb169874 |
200 | |
201 | use Moose::Role |
202 | |
203 | sub break { |
204 | |
205 | } |
206 | |
207 | If we compose both C<Breakable> and C<Breakdancer> in a class, we must |
208 | provide our own C<break> method: |
209 | |
210 | package FragileDancer; |
211 | |
212 | use Moose; |
213 | |
214 | with 'Breakable', 'Breakdancer'; |
ef45e915 |
215 | |
c56e5db4 |
216 | sub break { ... } |
217 | |
218 | =head1 METHOD EXCLUSION AND ALIASING |
219 | |
220 | If we want our C<FragileDancer> class to be able to call the methods |
221 | from both its roles, we can alias the methods: |
222 | |
223 | package FragileDancer; |
224 | |
225 | use Moose; |
226 | |
227 | with 'Breakable' => { alias => { break => 'break_bone' } }, |
228 | 'Breakdancer' => { alias => { break => 'break_dance' } }; |
229 | |
230 | However, aliasing a method simply makes a I<copy> of the method with |
231 | the new name. We also need to exclude the original name: |
232 | |
233 | with 'Breakable' => { |
ffb800c0 |
234 | alias => { break => 'break_bone' }, |
235 | excludes => 'break', |
c56e5db4 |
236 | }, |
237 | 'Breakdancer' => { |
ffb800c0 |
238 | alias => { break => 'break_dance' }, |
239 | excludes => 'break', |
c56e5db4 |
240 | }; |
241 | |
ffb800c0 |
242 | The excludes parameter prevents the C<break> method from being composed |
c56e5db4 |
243 | into the C<FragileDancer> class, so we don't have a conflict. This |
244 | means that C<FragileDancer> does not need to implement its own |
245 | C<break> method. |
246 | |
247 | This is useful, but it's worth noting that this breaks the contract |
248 | implicit in consuming a role. Our C<FragileDancer> class does both the |
249 | C<Breakable> and C<BreakDancer>, but does not provide a C<break> |
250 | method. If some API expects an object that does one of those roles, it |
251 | probably expects it to implement that method. |
252 | |
ca426a3a |
253 | In some use cases we might alias and exclude methods from roles, but |
254 | then provide a method of the same name in the class itself. |
255 | |
256 | =head1 ROLE EXCLUSION |
257 | |
258 | A role can say that it cannot be combined with some other role. This |
259 | should be used with great caution, since it limits the re-usability of |
260 | the role. |
261 | |
262 | package Breakable; |
263 | |
264 | use Moose::Role; |
265 | |
266 | excludes 'BreakDancer'; |
267 | |
a4bd85ad |
268 | =head1 AUTHOR |
269 | |
270 | Dave Rolsky E<lt>autarch@urth.orgE<gt> |
271 | |
272 | =head1 COPYRIGHT AND LICENSE |
273 | |
2840a3b2 |
274 | Copyright 2009 by Infinity Interactive, Inc. |
a4bd85ad |
275 | |
276 | L<http://www.iinteractive.com> |
277 | |
278 | This library is free software; you can redistribute it and/or modify |
279 | it under the same terms as Perl itself. |
280 | |
281 | =cut |