=head1 NAME
-Moose::Manual::Attribute - Moose's Method Modifiers
+Moose::Manual::MethodModifiers - Moose's method modifiers
=head1 WHAT IS A METHOD MODIFIER?
-Moose provides a feature called "method modifiers". Another word for
-this feature might be "hooks" or "advice".
+Moose provides a feature called "method modifiers". You can also think
+of these as "hooks" or "advice".
It's probably easiest to understand this feature with a few examples:
use Moose;
sub foo {
- print "foo\n";
+ print " foo\n";
}
before 'foo' => sub { print "about to call foo\n"; };
my $orig = shift;
my $self = shift;
- print "I'm around foo\n";
+ print " I'm around foo\n";
$self->$orig(@_);
- print "I'm still around foo\n";
+ print " I'm still around foo\n";
};
Now if I call C<< Example->new->foo >> I'll get the following output:
about to call foo
- I'm around foo
- foo
- I'm still around foo
+ I'm around foo
+ foo
+ I'm still around foo
just called foo
You probably could have figured that out from the names "before",
=head1 WHY USE THEM?
-Method modifiers have many uses. One very common use is in roles. This
-lets roles alter the behavior of methods in the classes that use
-them. See L<Moose::Manual::Roles> for more about roles.
+Method modifiers have many uses. They are often used in roles to alter the
+behavior of methods in the classes that consume the role. See
+L<Moose::Manual::Roles> for more information about roles.
-Modifiers really are at their most useful in roles, so some of the
-examples below are a bit artificial. They're intended to give you an
-idea of how modifiers work, but may not be the most natural usages.
+Since modifiers are mostly useful in roles, some of the examples below
+are a bit artificial. They're intended to give you an idea of how
+modifiers work, but may not be the most natural usage.
=head1 BEFORE, AFTER, AND AROUND
-Method modifiers can also be used to add behavior to a method that
-Moose generates for you, such as an attribute accessor:
+Method modifiers can be used to add behavior to a method that Moose
+generates for you, such as an attribute accessor:
has 'size' => ( is => 'rw' );
};
Another use for the before modifier would be to do some sort of
-pre-checking on a method call. For example:
+prechecking on a method call. For example:
before 'size' => sub {
my $self = shift;
if @_ && $self->is_growing;
};
-This lets us implement logical checks that don't fit well into
-constraints.
+This lets us implement logical checks that don't make sense as type
+constraints. In particular, they're useful for defining logical rules
+about an object's state changes.
Similarly, an after modifier could be used for logging an action that
was taken.
Note that the return values of both before and after modifiers are
ignored.
-An around modifier is a bit more powerful than either a before or
-after modifier. First, it is easy to modify the arguments being passed
-onto the original method in an around modifier. Second, you can decide
-to simply not call the original method at all, unlike with other
-modifiers. Finally, you can modify the return value with an around
-modifier.
+An around modifier is more powerful than either a before or
+after modifier. It can modify the arguments being passed to the
+original method, and you can even decide to simply not call the
+original method at all. You can also modify the return value with an
+around modifier.
An around modifier receives the original method as its first argument,
I<then> the object, and finally any arguments passed to the method.
return $self->$orig($size);
};
+C<before>, C<after>, and C<around> can also modify multiple methods
+at once. The simplest example of this is passing them as a list:
+
+ before [qw(foo bar baz)] => sub {
+ warn "something is being called!";
+ };
+
+This will add a C<before> modifier to each of the C<foo>, C<bar>,
+and C<baz> methods in the current class, just as though a separate
+call to C<before> was made for each of them. The list can be passed
+either as a bare list, or as an arrayref. Note that the name of the
+function being modified isn't passed in in any way; this syntax is
+only intended for cases where the function being modified doesn't
+actually matter. If the function name does matter, use something like this:
+
+ for my $func (qw(foo bar baz)) {
+ before $func => sub {
+ warn "$func was called!";
+ };
+ }
+
+In addition, you can specify a regular expression to indicate the
+methods to wrap, like so:
+
+ after qr/^command_/ => sub {
+ warn "got a command";
+ };
+
+This will match the regular expression against each method name
+returned by L<Class::MOP::Class/get_method_list>, and add a modifier
+to each one that matches. The same caveats apply as above. Using regular
+expressions to determine methods to wrap is quite a bit more powerful
+than the previous alternatives, but it's also quite a bit more
+dangerous. In particular, you should make sure to avoid wrapping
+methods with a special meaning to Moose or Perl, such as C<meta>, C<new>,
+C<BUILD>, C<DESTROY>, C<AUTOLOAD>, etc., as this could cause
+unintended (and hard to debug) problems.
+
=head1 INNER AND AUGMENT
Augment and inner are two halves of the same feature. The augment
augment 'as_xml' => sub {
my $self = shift;
- my $xml = "<report>\n";
+ my $xml = " <report>\n";
$xml .= inner();
- $xml .= "</report>\n";
+ $xml .= " </report>\n";
return $xml;
};
When we call C<as_xml> on a Report object, we get something like this:
<document>
- <report>
- </report>
+ <report>
+ </report>
</document>
But we also called C<inner()> in C<Report>, so we can continue
augment 'as_xml' => sub {
my $self = shift;
- my $xml = '<income>' . $self->income . '</income>';
+ my $xml = ' <income>' . $self->income . '</income>';
$xml .= "\n";
- my $xml = '<expenses>' . $self->expenses . '</expenses>';
+ $xml .= ' <expenses>' . $self->expenses . '</expenses>';
$xml .= "\n";
$xml .= inner() || q{};
Now our report has some content:
<document>
- <report>
- <income>$10</income>
- <expenses>$8</expenses>
- </report>
+ <report>
+ <income>$10</income>
+ <expenses>$8</expenses>
+ </report>
</document>
What makes this combination of C<augment> and C<inner()> special is
that it allows us to have methods which are called from parent (least
-specific) to child (most specific). This inverts the normal order,
-where the child's method is called first, and it in turn will call C<<
-$self->SUPER::method >> to call the parent.
+specific) to child (most specific). This inverts the normal
+inheritance pattern.
-Note that in C<Report::IncomeAndExpenses> we call C<inner()> again. If
-the object is an instance of C<Report::IncomeAndExpenses> then this
-call is a no-op, and just returns false.
+Note that in C<Report::IncomeAndExpenses> we call C<inner()> again. If the
+object is an instance of C<Report::IncomeAndExpenses> then this call is a
+no-op, and just returns false. It's a good idea to always call C<inner()> to
+allow for future subclassing.
=head1 OVERRIDE AND SUPER
=head1 COPYRIGHT AND LICENSE
-Copyright 2008 by Infinity Interactive, Inc.
+Copyright 2008-2010 by Infinity Interactive, Inc.
L<http://www.iinteractive.com>