NAME
Zydeco::Manual::06_MethodModifiers - Method modifiers to easily wrap or override inherited methods
SYNOPSIS
package MyApp {
use Zydeco;
class Event {
has date;
method occur () {
...;
}
}
class Wedding extends Event {
before occur {
say "Speak now or forever hold your peace";
}
after occur {
say "You may kiss the bride";
}
}
}
MANUAL
Zydeco allows subclasses to modify the methods they inherit from their parents, allow roles to modify the methods in the classes that consume them, and allow classes to modify the methods they consume from roles.
before
and after
modifiers.
A before
modifier executes before the original method is called. Its return value is ignored. If it throws an exception, this will prevent the original method from being caused.
An after
modifier executes after the original method is called. Its return value is also ignored.
Both of these modifiers may see the parameters passed to the original method.
role Event {
method set_host (Person $host) {
...;
}
}
class LegalIssue with Throwable;
class Wedding with Event {
before set_host (Person $host) {
$host->has_licence or LegalIssue->throw;
}
}
Like with method definitions, $self
and $class
are available.
Note that signatures are checked separately by the modifier and the original method. So it will be checked twice that $host
is a Person object. Because checking is performed at run-time, for performance you may wish to simplify the signature in your modifiers.
role Event {
method set_host (Person $host) {
...;
}
}
class LegalIssue with Throwable;
class Wedding with Event {
before set_host ($host) {
$host->has_licence or LegalIssue->throw;
}
}
This is especially true for after
modifiers, where the modifiers can be confident that the parameters have already passed the original method's signature checks.
around
modifiers.
Unlike before
and after
modifiers, around
modifiers can modify the arguments passed to the original method, can change the return value, and can even prevent the original method from being called. They allow you to wrap the original method in arbitrary ways.
Here's an example:
package MyApp;
use Zydeco;
class PriceAdder {
method add_prices ( ArrayRef[Num] $prices ) {
my $sum = 0;
$sum += $_ for @$prices;
return $sum;
}
}
class PriceAdder::WithCommission extends PriceAdder {
has commission = 0; # percent
around add_prices ( $prices ) {
my $sum = $self->$next( $prices );
return $sum * ( 1 + ($self->commission/100) );
}
}
my $adder = MyApp->new_priceadder_withcommission( commission => 5 );
say $adder->add_prices( [ 100, 400, 500 ] ); # ==> 1050
Like with method definitions, $self
and $class
are available. $next
is also defined which contains a coderef for the next method to call. This may be the original method itself, but it may be another wrapper.
If no signature is given, $next
is passed as part of @_
before the invocant.
KEYWORDS
In this chapter, we looked at the following keywords:
before
after
around
NEXT STEPS
TODO.
AUTHOR
Toby Inkster <tobyink@cpan.org>.
COPYRIGHT AND LICENCE
This software is copyright (c) 2020 by Toby Inkster.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
DISCLAIMER OF WARRANTIES
THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.