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.2203
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 subclassing
282       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 it
313       allows us to have methods which are called from parent (least specific)
314       to child (most specific). This inverts the normal inheritance pattern.
315
316       Note that in "Report::IncomeAndExpenses" we call inner() again. If the
317       object is an instance of "Report::IncomeAndExpenses" then this call is
318       a no-op, and just returns false. It's a good idea to always call
319       inner() to allow for future subclassing.
320

OVERRIDE AND SUPER

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

SEMI-COLONS

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

EXCEPTIONS AND STACK TRACES

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

CAVEATS

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

AUTHORS

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