1Class::Method::ModifierUss(e3r)Contributed Perl DocumentCaltaisosn::Method::Modifiers(3)
2
3
4
6 Class::Method::Modifiers - Provides Moose-like method modifiers
7
9 version 2.13
10
12 package Child;
13 use parent 'MyParent';
14 use Class::Method::Modifiers;
15
16 sub new_method { }
17
18 before 'old_method' => sub {
19 carp "old_method is deprecated, use new_method";
20 };
21
22 around 'other_method' => sub {
23 my $orig = shift;
24 my $ret = $orig->(@_);
25 return $ret =~ /\d/ ? $ret : lc $ret;
26 };
27
28 after 'private', 'protected' => sub {
29 debug "finished calling a dangerous method";
30 };
31
32 use Class::Method::Modifiers qw(fresh);
33
34 fresh 'not_in_hierarchy' => sub {
35 warn "freshly added method\n";
36 };
37
39 Method modifiers are a convenient feature from the CLOS (Common Lisp
40 Object System) world.
41
42 In its most basic form, a method modifier is just a method that calls
43 "$self->SUPER::foo(@_)". I for one have trouble remembering that exact
44 invocation, so my classes seldom re-dispatch to their base classes.
45 Very bad!
46
47 "Class::Method::Modifiers" provides three modifiers: "before",
48 "around", and "after". "before" and "after" are run just before and
49 after the method they modify, but can not really affect that original
50 method. "around" is run in place of the original method, with a hook to
51 easily call that original method. See the "MODIFIERS" section for more
52 details on how the particular modifiers work.
53
54 One clear benefit of using "Class::Method::Modifiers" is that you can
55 define multiple modifiers in a single namespace. These separate
56 modifiers don't need to know about each other. This makes top-down
57 design easy. Have a base class that provides the skeleton methods of
58 each operation, and have plugins modify those methods to flesh out the
59 specifics.
60
61 Parent classes need not know about "Class::Method::Modifiers". This
62 means you should be able to modify methods in any subclass. See
63 Term::VT102::ZeroBased for an example of subclassing with
64 "Class::Method::Modifiers".
65
66 In short, "Class::Method::Modifiers" solves the problem of making sure
67 you call "$self->SUPER::foo(@_)", and provides a cleaner interface for
68 it.
69
70 As of version 1.00, "Class::Method::Modifiers" is faster in some cases
71 than Moose. See benchmark/method_modifiers.pl in the Moose
72 distribution.
73
74 "Class::Method::Modifiers" also provides an additional "modifier" type,
75 "fresh"; see below.
76
78 All modifiers let you modify one or multiple methods at a time. The
79 names of multiple methods can be provided as a list or as an array-
80 reference. Examples:
81
82 before 'method' => sub { ... };
83 before 'method1', 'method2' => sub { ... };
84 before [ 'method1', 'method2' ] => sub { ... };
85
86 before method(s) => sub { ... };
87 "before" is called before the method it is modifying. Its return value
88 is totally ignored. It receives the same @_ as the method it is
89 modifying would have received. You can modify the @_ the original
90 method will receive by changing $_[0] and friends (or by changing
91 anything inside a reference). This is a feature!
92
93 after method(s) => sub { ... };
94 "after" is called after the method it is modifying. Its return value is
95 totally ignored. It receives the same @_ as the method it is modifying
96 received, mostly. The original method can modify @_ (such as by
97 changing $_[0] or references) and "after" will see the modified
98 version. If you don't like this behavior, specify both a "before" and
99 "after", and copy the @_ during "before" for "after" to use.
100
101 around method(s) => sub { ... };
102 "around" is called instead of the method it is modifying. The method
103 you're overriding is passed in as the first argument (called $orig by
104 convention). Watch out for contextual return values of $orig.
105
106 You can use "around" to:
107
108 Pass $orig a different @_
109 around 'method' => sub {
110 my $orig = shift;
111 my $self = shift;
112 $orig->($self, reverse @_);
113 };
114
115 Munge the return value of $orig
116 around 'method' => sub {
117 my $orig = shift;
118 ucfirst $orig->(@_);
119 };
120
121 Avoid calling $orig -- conditionally
122 around 'method' => sub {
123 my $orig = shift;
124 return $orig->(@_) if time() % 2;
125 return "no dice, captain";
126 };
127
128 fresh method(s) => sub { ... };
129 (Available since version 2.00)
130
131 Unlike the other modifiers, this does not modify an existing method.
132 Ordinarily, "fresh" merely installs the coderef as a method in the
133 appropriate class; but if the class hierarchy already contains a method
134 of the same name, an exception is thrown. The idea of this "modifier"
135 is to increase safety when subclassing. Suppose you're writing a
136 subclass of a class Some::Base, and adding a new method:
137
138 package My::Subclass;
139 use base 'Some::Base';
140
141 sub foo { ... }
142
143 If a later version of Some::Base also adds a new method named "foo",
144 your method will shadow that method. Alternatively, you can use
145 "fresh" to install the additional method into your subclass:
146
147 package My::Subclass;
148 use base 'Some::Base';
149
150 use Class::Method::Modifiers 'fresh';
151
152 fresh 'foo' => sub { ... };
153
154 Now upgrading Some::Base to a version with a conflicting "foo" method
155 will cause an exception to be thrown; seeing that error will give you
156 the opportunity to fix the problem (perhaps by picking a different
157 method name in your subclass, or similar).
158
159 Creating fresh methods with "install_modifier" (see below) provides a
160 way to get similar safety benefits when adding local monkeypatches to
161 existing classes; see
162 <http://aaroncrane.co.uk/talks/monkey_patching_subclassing/>.
163
164 For API compatibility reasons, this function is exported only when you
165 ask for it specifically, or for ":all".
166
167 install_modifier $package, $type, @names, sub { ... }
168 "install_modifier" is like "before", "after", "around", and "fresh" but
169 it also lets you dynamically select the modifier type ('before',
170 'after', 'around', 'fresh') and package that the method modifiers are
171 installed into. This expert-level function is exported only when you
172 ask for it specifically, or for ":all".
173
175 All three normal modifiers; "before", "after", and "around"; are
176 exported into your namespace by default. You may "use
177 Class::Method::Modifiers ()" to avoid modifying your namespace. I may
178 steal more features from Moose, namely "super", "override", "inner",
179 "augment", and whatever the Moose folks come up with next.
180
181 Note that the syntax and semantics for these modifiers is directly
182 borrowed from Moose (the implementations, however, are not).
183
184 Class::Trigger shares a few similarities with
185 "Class::Method::Modifiers", and they even have some overlap in purpose
186 -- both can be used to implement highly pluggable applications. The
187 difference is that Class::Trigger provides a mechanism for easily
188 letting parent classes to invoke hooks defined by other code.
189 "Class::Method::Modifiers" provides a way of overriding/augmenting
190 methods safely, and the parent class need not know about it.
191
192 :lvalue METHODS
193 When adding "before" or "after" modifiers, the wrapper method will be
194 an lvalue method if the wrapped sub is, and assigning to the method
195 will propagate to the wrapped method as expected. For "around"
196 modifiers, it is the modifier sub that determines if the wrapper method
197 is an lvalue method.
198
200 It is erroneous to modify a method that doesn't exist in your class's
201 inheritance hierarchy. If this occurs, an exception will be thrown when
202 the modifier is defined.
203
204 It doesn't yet play well with "caller". There are some "TODO" tests for
205 this. Don't get your hopes up though!
206
207 Applying modifiers to array lvalue methods is not fully supported.
208 Attempting to assign to an array lvalue method that has an "after"
209 modifier applied will result in an error. Array lvalue methods are not
210 well supported by perl in general, and should be avoided.
211
213 This module was bumped to 1.00 following a complete reimplementation,
214 to indicate breaking backwards compatibility. The "guard" modifier was
215 removed, and the internals are completely different.
216
217 The new version is a few times faster with half the code. It's now even
218 faster than Moose.
219
220 Any code that just used modifiers should not change in behavior, except
221 to become more correct. And, of course, faster. :)
222
224 · Class::Method::Modifiers::Fast
225
226 · Moose
227
228 · Class::Trigger
229
230 · Class::MOP::Method::Wrapped
231
232 · MRO::Compat
233
234 · CLOS <https://en.wikipedia.org/wiki/Common_Lisp_Object_System>
235
237 Thanks to Stevan Little for Moose, I would never have known about
238 method modifiers otherwise.
239
240 Thanks to Matt Trout and Stevan Little for their advice.
241
243 Bugs may be submitted through the RT bug tracker
244 <https://rt.cpan.org/Public/Dist/Display.html?Name=Class-Method-
245 Modifiers> (or bug-Class-Method-Modifiers@rt.cpan.org <mailto:bug-
246 Class-Method-Modifiers@rt.cpan.org>).
247
249 Shawn M Moore <sartak@gmail.com>
250
252 · Karen Etheridge <ether@cpan.org>
253
254 · Shawn M Moore <code@sartak.org>
255
256 · Graham Knop <haarg@haarg.org>
257
258 · Aaron Crane <arc@cpan.org>
259
260 · Peter Rabbitson <ribasushi@cpan.org>
261
262 · Justin Hunter <justin.d.hunter@gmail.com>
263
264 · David Steinbrunner <dsteinbrunner@pobox.com>
265
266 · gfx <gfuji@cpan.org>
267
268 · mannih <github@lxxi.org>
269
271 This software is copyright (c) 2007 by Shawn M Moore.
272
273 This is free software; you can redistribute it and/or modify it under
274 the same terms as the Perl 5 programming language system itself.
275
276
277
278perl v5.30.1 2020-01-29 Class::Method::Modifiers(3)