Trying to understand Moose:
use Modern::Perl;
package FOO {
use Moose;
sub rep { say " <report></report>"; }
sub doc {
say "<document>";
inner();
say "</document>";
}
}
package BAR {
use Moose;
extends 'FOO';
around 'rep' => sub {
my $orig = shift;
my $self = shift;
say "<document>";
$self->$orig(@_);
say "</document>";
};
augment 'doc' => sub {
say " <report></report>";
};
}
package main {
BAR->new->rep;
say "===";
BAR->new->doc;
}
Produces...
<document>
<report></report>
</document>
===
<document>
<report></report>
</document>
... the same result. When desinging the "model (object hierarchy)" - based on what I should decide when to use around
and when augment
?
Here are probably other (deeper) things what i currently didn't understand yet.
Can please someone provide an "more deep" explanation, because reading tru the Moose/Manual/MethodModifiers obviously not helped enough...
augment
and around
do rather different things. augment
is designed to make this sort of pattern easier:
package Document {
use Moose;
sub make_document {
my $self = shift;
return "<doc>" . $self->_document_innards . "</doc>"
}
# stub; override in child class
sub _document_innards {
my $self = shift;
return "";
}
}
package Invoice {
use Moose;
extends 'Document';
sub _document_innards {
my $self = shift;
return "Give me money!";
}
}
With augment
it becomes:
package Document {
use Moose;
sub make_document {
my $self = shift;
return "<doc>" . inner() . "</doc>"
}
}
package Invoice {
use Moose;
extends 'Document';
augment make_document => sub {
my $self = shift;
return "Give me money!";
};
}
On the other hand, around
is used as a replacement for doing $self->SUPER::method(@args)
because SUPER
can't work in roles (the notion of which package to check superclasses for is bound at compile-time, so $self->SUPER::method(@args)
would check superclasses of the role (i.e. none) instead of superclasses of the class that consumed the role. If you're not using roles, then SUPER
can still be used in Moose classes just fine. TLDR: SUPER
is broken by roles, so Moose gives you around
as an alternative.
Another thing to compare is override
which is a bit like around
, but gives you this super()
function which is perhaps slightly cleaner than $self->$orig(@_)
. It also has an "there can be only one" feature. If two roles try to provide an around
modifier for the same method, that's fine: they both get to wrap the method (though the order in which they are applied is undefined). If two roles try to provide an override
modifier, that's an error.
The implementation of augment
is somewhat fragile in my experience, so that in my book is a reason to avoid it. Don't try to replace it with around
, because they do rather different things. Instead, replace it with the pattern used in my first example above.
Using around
should always be your first instinct. As (Moose creator) Stevan Little says about augment
:
Thankfully, only a small percentage of people actually grok this feature and of those people only a handful of them are crazy enough to try and use it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With