1Moose::Manual::MethodMoUdsiefrieCrosn(t3r)ibuted Perl DoMcouomseen:t:aMtainounal::MethodModifiers(3)
2
3
4

NAME

6       Moose::Manual::MethodModifiers - Moose's method modifiers
7

VERSION

9       version 2.2015
10

WHAT IS A METHOD MODIFIER?

12       Moose provides a feature called "method modifiers". You can also think
13       of these as "hooks" or "advice".
14
15       It's probably easiest to understand this feature with a few examples:
16
17         package Example;
18
19         use Moose;
20
21         sub foo {
22             print "    foo\n";
23         }
24
25         before 'foo' => sub { print "about to call foo\n"; };
26         after 'foo'  => sub { print "just called foo\n"; };
27
28         around 'foo' => sub {
29             my $orig = shift;
30             my $self = shift;
31
32             print "  I'm around foo\n";
33
34             $self->$orig(@_);
35
36             print "  I'm still around foo\n";
37         };
38
39       Now if I call "Example->new->foo" I'll get the following output:
40
41         about to call foo
42           I'm around foo
43             foo
44           I'm still around foo
45         just called foo
46
47       You probably could have figured that out from the names "before",
48       "after", and "around".
49
50       Also, as you can see, the before modifiers come before around
51       modifiers, and after modifiers come last.
52
53       When there are multiple modifiers of the same type, the before and
54       around modifiers run from the last added to the first, and after
55       modifiers run from first added to last:
56
57          before 2
58           before 1
59            around 2
60             around 1
61              primary
62             around 1
63            around 2
64           after 1
65          after 2
66

WHY USE THEM?

68       Method modifiers have many uses. They are often used in roles to alter
69       the behavior of methods in the classes that consume the role. See
70       Moose::Manual::Roles for more information about roles.
71
72       Since modifiers are mostly useful in roles, some of the examples below
73       are a bit artificial. They're intended to give you an idea of how
74       modifiers work, but may not be the most natural usage.
75

BEFORE, AFTER, AND AROUND

77       Method modifiers can be used to add behavior to methods without
78       modifying the definition of those methods.
79
80   Before and after Modifiers
81       Method modifiers can be used to add behavior to a method that Moose
82       generates for you, such as an attribute accessor:
83
84         has 'size' => ( is => 'rw' );
85
86         before 'size' => sub {
87             my $self = shift;
88
89             if (@_) {
90                 Carp::cluck('Someone is setting size');
91             }
92         };
93
94       Another use for the before modifier would be to do some sort of
95       prechecking on a method call. For example:
96
97         before 'size' => sub {
98             my $self = shift;
99
100             die 'Cannot set size while the person is growing'
101                 if @_ && $self->is_growing;
102         };
103
104       This lets us implement logical checks that don't make sense as type
105       constraints. In particular, they're useful for defining logical rules
106       about an object's state changes.
107
108       Similarly, an after modifier could be used for logging an action that
109       was taken.
110
111       Note that the return values of both before and after modifiers are
112       ignored.
113
114   Around modifiers
115       An around modifier is more powerful than either a before or after
116       modifier. It can modify the arguments being passed to the original
117       method, and you can even decide to simply not call the original method
118       at all. You can also modify the return value with an around modifier.
119
120       An around modifier receives the original method as its first argument,
121       then the object, and finally any arguments passed to the method.
122
123         around 'size' => sub {
124             my $orig = shift;
125             my $self = shift;
126
127             return $self->$orig()
128                 unless @_;
129
130             my $size = shift;
131             $size = $size / 2
132                 if $self->likes_small_things();
133
134             return $self->$orig($size);
135         };
136
137   Wrapping multiple methods at once
138       "before", "after", and "around" can also modify multiple methods at
139       once. The simplest example of this is passing them as a list:
140
141         before [qw(foo bar baz)] => sub {
142             warn "something is being called!";
143         };
144
145       This will add a "before" modifier to each of the "foo", "bar", and
146       "baz" methods in the current class, just as though a separate call to
147       "before" was made for each of them. The list can be passed either as a
148       bare list, or as an arrayref. Note that the name of the function being
149       modified isn't passed in in any way; this syntax is only intended for
150       cases where the function being modified doesn't actually matter. If the
151       function name does matter, use something like this:
152
153         for my $func (qw(foo bar baz)) {
154             before $func => sub {
155                 warn "$func was called!";
156             };
157         }
158
159   Using regular expressions to select methods to wrap
160       In addition, you can specify a regular expression to indicate the
161       methods to wrap, like so:
162
163         after qr/^command_/ => sub {
164             warn "got a command";
165         };
166
167       This will match the regular expression against each method name
168       returned by "get_method_list" in Class::MOP::Class, and add a modifier
169       to each one that matches. The same caveats apply as above.
170
171       Using regular expressions to determine methods to wrap is quite a bit
172       more powerful than the previous alternatives, but it's also quite a bit
173       more dangerous.  Bear in mind that if your regular expression matches
174       certain Perl and Moose reserved method names with a special meaning to
175       Moose or Perl, such as "meta", "new", "BUILD", "DESTROY", "AUTOLOAD",
176       etc, this could cause unintended (and hard to debug) problems and is
177       best avoided.
178
179   Execution order of method modifiers and inheritance
180       When both a superclass and an inheriting class have the same method
181       modifiers, the method modifiers of the inheriting class are wrapped
182       around the method modifiers of the superclass, as the following example
183       illustrates:
184
185       Here is the parent class:
186
187         package Superclass;
188         use Moose;
189         sub rant { printf "        RANTING!\n" }
190         before 'rant' => sub { printf "    In %s before\n", __PACKAGE__ };
191         after 'rant'  => sub { printf "    In %s after\n",  __PACKAGE__ };
192         around 'rant' => sub {
193             my $orig = shift;
194             my $self = shift;
195             printf "      In %s around before calling original\n", __PACKAGE__;
196             $self->$orig;
197             printf "      In %s around after calling original\n", __PACKAGE__;
198         };
199         1;
200
201       And the child class:
202
203         package Subclass;
204         use Moose;
205         extends 'Superclass';
206         before 'rant' => sub { printf "In %s before\n", __PACKAGE__ };
207         after 'rant'  => sub { printf "In %s after\n",  __PACKAGE__ };
208         around 'rant' => sub {
209             my $orig = shift;
210             my $self = shift;
211             printf "  In %s around before calling original\n", __PACKAGE__;
212             $self->$orig;
213             printf "  In %s around after calling original\n", __PACKAGE__;
214         };
215         1;
216
217       And here's the output when we call the wrapped method ("Child->rant"):
218
219         % perl -MSubclass -e 'Subclass->new->rant'
220
221         In Subclass before
222           In Subclass around before calling original
223             In Superclass before
224               In Superclass around before calling original
225                 RANTING!
226               In Superclass around after calling original
227             In Superclass after
228           In Subclass around after calling original
229         In Subclass after
230

INNER AND AUGMENT

232       Augment and inner are two halves of the same feature. The augment
233       modifier provides a sort of inverted subclassing. You provide part of
234       the implementation in a superclass, and then document that subclasses
235       are expected to provide the rest.
236
237       The superclass calls "inner()", which then calls the "augment" modifier
238       in the subclass:
239
240         package Document;
241
242         use Moose;
243
244         sub as_xml {
245             my $self = shift;
246
247             my $xml = "<document>\n";
248             $xml .= inner();
249             $xml .= "</document>\n";
250
251             return $xml;
252         }
253
254       Using "inner()" in this method makes it possible for one or more
255       subclasses to then augment this method with their own specific
256       implementation:
257
258         package Report;
259
260         use Moose;
261
262         extends 'Document';
263
264         augment 'as_xml' => sub {
265             my $self = shift;
266
267             my $xml = "  <report>\n";
268             $xml .= inner();
269             $xml .= "  </report>\n";
270
271             return $xml;
272         };
273
274       When we call "as_xml" on a Report object, we get something like this:
275
276         <document>
277           <report>
278           </report>
279         </document>
280
281       But we also called "inner()" in "Report", so we can continue
282       subclassing and adding more content inside the document:
283
284         package Report::IncomeAndExpenses;
285
286         use Moose;
287
288         extends 'Report';
289
290         augment 'as_xml' => sub {
291             my $self = shift;
292
293             my $xml = '    <income>' . $self->income . '</income>';
294             $xml .= "\n";
295             $xml .= '    <expenses>' . $self->expenses . '</expenses>';
296             $xml .= "\n";
297
298             $xml .= inner() || q{};
299
300             return $xml;
301         };
302
303       Now our report has some content:
304
305         <document>
306           <report>
307             <income>$10</income>
308             <expenses>$8</expenses>
309           </report>
310         </document>
311
312       What makes this combination of "augment" and "inner()" special is that
313       it allows us to have methods which are called from parent (least
314       specific) to child (most specific). This inverts the normal inheritance
315       pattern.
316
317       Note that in "Report::IncomeAndExpenses" we call "inner()" again. If
318       the object is an instance of "Report::IncomeAndExpenses" then this call
319       is a no-op, and just returns false. It's a good idea to always call
320       "inner()" to allow for future subclassing.
321

OVERRIDE AND SUPER

323       Finally, Moose provides some simple sugar for Perl's built-in method
324       overriding scheme. If you want to override a method from a parent
325       class, you can do this with "override":
326
327         package Employee;
328
329         use Moose;
330
331         extends 'Person';
332
333         has 'job_title' => ( is => 'rw' );
334
335         override 'display_name' => sub {
336             my $self = shift;
337
338             return super() . q{, } . $self->job_title();
339         };
340
341       The call to "super()" is almost the same as calling
342       "$self->SUPER::display_name". The difference is that the arguments
343       passed to the superclass's method will always be the same as the ones
344       passed to the method modifier, and cannot be changed.
345
346       All arguments passed to "super()" are ignored, as are any changes made
347       to @_ before "super()" is called.
348

SEMI-COLONS

350       Because all of these method modifiers are implemented as Perl
351       functions, you must always end the modifier declaration with a semi-
352       colon:
353
354         after 'foo' => sub { };
355

EXCEPTIONS AND STACK TRACES

357       An exception thrown in a "before" modifier will prevent the method it
358       modifies from being called at all. An exception in an "around" modifier
359       may prevent the modified method from being called, depending on how the
360       "around" modifier is structured. An exception in an "after" modifier
361       obviously cannot prevent the method it wraps from being called.
362
363       Both "override" and "augment" are similar to "around" in that they can
364       decide whether or not to call the method they modify before or after
365       throwing an exception.
366
367       From the caller's perspective, an exception in a method modifier will
368       look like the method it called threw an exception. However, method
369       modifiers are just standard Perl subroutines. This means that they end
370       up on the stack in stack traces as an additional frame.
371

CAVEATS

373       These method modification features do not work well with multiple
374       inheritance, due to how method resolution is performed in Perl.
375       Experiment with a test program to ensure your class hierarchy works as
376       expected, or more preferably, don't use multiple inheritance (roles can
377       help with this)!
378

AUTHORS

380       •   Stevan Little <stevan@cpan.org>
381
382       •   Dave Rolsky <autarch@urth.org>
383
384       •   Jesse Luehrs <doy@cpan.org>
385
386       •   Shawn M Moore <sartak@cpan.org>
387
388       •   יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
389
390       •   Karen Etheridge <ether@cpan.org>
391
392       •   Florian Ragwitz <rafl@debian.org>
393
394       •   Hans Dieter Pearcey <hdp@cpan.org>
395
396       •   Chris Prather <chris@prather.org>
397
398       •   Matt S Trout <mstrout@cpan.org>
399
401       This software is copyright (c) 2006 by Infinity Interactive, Inc.
402
403       This is free software; you can redistribute it and/or modify it under
404       the same terms as the Perl 5 programming language system itself.
405
406
407
408perl v5.34.0                      2021-07-22 Moose::Manual::MethodModifiers(3)
Impressum