1Moose::Manual::DelegatiUosne(r3)Contributed Perl DocumenMtoaotsieo:n:Manual::Delegation(3)
2
3
4
6 Moose::Manual::Delegation - Attribute delegation
7
9 version 2.2013
10
12 Delegation is a feature that lets you create "proxy" methods that do
13 nothing more than call some other method on an attribute. This lets you
14 simplify a complex set of "has-a" relationships and present a single
15 unified API from one class.
16
17 With delegation, consumers of a class don't need to know about all the
18 objects it contains, reducing the amount of API they need to learn.
19
20 Delegations are defined as a mapping between one or more methods
21 provided by the "real" class (the delegatee), and a set of
22 corresponding methods in the delegating class. The delegating class can
23 re-use the method names provided by the delegatee or provide its own
24 names.
25
26 Delegation is also a great way to wrap an existing class, especially a
27 non-Moose class or one that is somehow hard (or impossible) to
28 subclass.
29
31 Moose offers a number of options for defining a delegation's mapping,
32 ranging from simple to complex.
33
34 The simplest form is to simply specify a list of methods:
35
36 package Website;
37
38 use Moose;
39
40 has 'uri' => (
41 is => 'ro',
42 isa => 'URI',
43 handles => [qw( host path )],
44 );
45
46 Using an arrayref tells Moose to create methods in your class that
47 match the method names in the delegated class.
48
49 With this definition, we can call "$website->host" and it "just works".
50 Under the hood, Moose will call "$website->uri->host" for you. Note
51 that $website is not automatically passed to the "host" method; the
52 invocant is "$website->uri".
53
54 We can also define a mapping as a hash reference. This allows you to
55 rename methods as part of the mapping:
56
57 package Website;
58
59 use Moose;
60
61 has 'uri' => (
62 is => 'ro',
63 isa => 'URI',
64 handles => {
65 hostname => 'host',
66 path => 'path',
67 },
68 );
69
70 Using a hash tells Moose to create method names (specified on the left)
71 which invoke the delegated class methods (specified on the right).
72
73 In this example, we've created a "$website->hostname" method, rather
74 than simply using "URI.pm"'s name, "host" in the Website class.
75
76 These two mapping forms are the ones you will use most often. The
77 remaining methods are a bit more complex.
78
79 has 'uri' => (
80 is => 'ro',
81 isa => 'URI',
82 handles => qr/^(?:host|path|query.*)/,
83 );
84
85 This is similar to the array version, except it uses the regex to match
86 against all the methods provided by the delegatee. In order for this to
87 work, you must provide an "isa" parameter for the attribute, and it
88 must be a class. Moose uses this to introspect the delegatee class and
89 determine what methods it provides.
90
91 You can use a role name as the value of "handles":
92
93 has 'uri' => (
94 is => 'ro',
95 isa => 'URI',
96 handles => 'HasURI',
97 );
98
99 Moose will introspect the role to determine what methods it provides
100 and create a name-for-name mapping for each of those methods.
101
102 Finally, you can provide a sub reference to generate a mapping that
103 behaves like the hash example above. You probably won't need this
104 version often (if ever). See the Moose docs for more details on exactly
105 how this works.
106
108 Native delegations allow you to delegate to standard Perl data
109 structures as if they were objects.
110
111 has 'queue' => (
112 traits => ['Array'],
113 isa => 'ArrayRef[Item]',
114 default => sub { [ ] },
115 handles => {
116 add_item => 'push',
117 next_item => 'shift',
118 },
119 )
120
121 The "Array" trait in the "traits" parameter tells Moose that you would
122 like to use the set of Array helpers. Moose will then create "add_item"
123 and "next_item" methods that "just work". Behind the scenes "add_item"
124 is something like
125
126 sub add_item {
127 my ($self, @items) = @_;
128
129 for my $item (@items) {
130 $Item_TC->validate($item);
131 }
132
133 push @{ $self->queue }, @items;
134 }
135
136 For example, you might use Array helpers to add "add_task" and
137 "add_appointment" methods to a Calendar class:
138
139 has 'tasks' => (
140 traits => ['Array'],
141 isa => 'ArrayRef[Task]',
142 default => sub { [ ] },
143 handles => {
144 add_task => 'push',
145 next_task => 'shift',
146 },
147 );
148
149 has 'appointments' => (
150 traits => ['Array'],
151 isa => 'ArrayRef[Appointment]',
152 default => sub { [ ] },
153 handles => {
154 add_appointment => 'push',
155 next_appointment => 'shift',
156 },
157 );
158
159 Which you would call as:
160
161 $calendar->add_task( $task_obj );
162 $calendar->add_appointment( $appointment_obj );
163
164 As mentioned above, each trait provides a number of methods which are
165 summarized below. For more information about each of these provided
166 methods see the documentation for that specific trait.
167
168 Moose includes the following traits for native delegation.
169
170 · Array
171
172 The following methods are provided by the native Array trait:
173
174 count, is_empty, elements, get, pop, push, shift, unshift, splice,
175 first, first_index, grep, map, reduce, sort, sort_in_place,
176 shuffle, uniq, join, set, delete, insert, clear, accessor,
177 natatime, shallow_clone
178
179 · Bool
180
181 The following methods are provided by the native Bool trait:
182
183 set, unset, toggle, not
184
185 · Code
186
187 The following methods are provided by the native Code trait:
188
189 execute, execute_method
190
191 · Counter
192
193 The following methods are provided by the native Counter trait:
194
195 set, inc, dec, reset
196
197 · Hash
198
199 The following methods are provided by the native Hash trait:
200
201 get, set, delete, keys, exists, defined, values, kv, elements,
202 clear, count, is_empty, accessor, shallow_clone
203
204 · Number
205
206 The following methods are provided by the native Number trait:
207
208 add, sub, mul, div, mod, abs
209
210 · String
211
212 The following methods are provided by the native String trait:
213
214 inc, append, prepend, replace, match, chop, chomp, clear, length,
215 substr
216
218 Currying allows you to create a method with some pre-set parameters.
219 You can create a curried delegation method:
220
221 package Spider;
222 use Moose;
223
224 has request => (
225 is => 'ro'
226 isa => 'HTTP::Request',
227 handles => {
228 set_user_agent => [ header => 'UserAgent' ],
229 },
230 )
231
232 With this definition, calling "$spider->set_user_agent('MyClient')"
233 will call "$spider->request->header('UserAgent', 'MyClient')" behind
234 the scenes.
235
236 Note that with currying, the currying always starts with the first
237 parameter to a method ($_[0]). Any arguments you pass to the delegation
238 come after the curried arguments.
239
241 It is perfectly valid to delegate methods to an attribute which is not
242 required or can be undefined. When a delegated method is called, Moose
243 will throw a runtime error if the attribute does not contain an object.
244
246 · Stevan Little <stevan.little@iinteractive.com>
247
248 · Dave Rolsky <autarch@urth.org>
249
250 · Jesse Luehrs <doy@tozt.net>
251
252 · Shawn M Moore <code@sartak.org>
253
254 · יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
255
256 · Karen Etheridge <ether@cpan.org>
257
258 · Florian Ragwitz <rafl@debian.org>
259
260 · Hans Dieter Pearcey <hdp@weftsoar.net>
261
262 · Chris Prather <chris@prather.org>
263
264 · Matt S Trout <mst@shadowcat.co.uk>
265
267 This software is copyright (c) 2006 by Infinity Interactive, Inc.
268
269 This is free software; you can redistribute it and/or modify it under
270 the same terms as the Perl 5 programming language system itself.
271
272
273
274perl v5.32.0 2020-07-28 Moose::Manual::Delegation(3)