使用 Moose 进行编程/语法/before、after 和 around
外观
< 使用 Moose 进行编程 | 语法
before
、after
和 around
是方法修饰符。它们控制围绕实际方法调用的一系列事件,允许用户轻松执行简单的操作。两个关键字 before
和 after
只是触发代码,而 around
允许动态重写参数。
这些功能只在 Class::MOP
中有记录。
package Jerk;
use Moose;
sub fart {
print '\me farts';
}
before 'fart' => sub {
print '\me laughs';
};
package main;
my $m = Jerk->new;
$m->fart;
package Manners;
use Moose;
sub fart {
print '\me farts';
}
after 'fart' => sub {
print 'excuse me';
};
package main;
my $m = Manners->new;
$m->fart;
本节内容为存根。 您可以通过扩展它来帮助维基教科书。 |
# return an array ref, de-referenced.
around foo => sub {
my $sub = shift;
my $ret = $sub->(@_);
@{ $ret }
}
# auto-instantiate an empty array for a hash value
around foo_lookup => sub {
my ($next, $this, $key) = @_;
my $arrayref = $this->$next($key);
$arrayref ||= $this->foo_hashref->{$key} = [];
return $arrayref;
};
您可能很想在修饰符的子程序中调用修饰符所附加的函数。这很糟糕,请观察以下内容,并且永远不要这样做。
has 'foo' => ( isa => 'Int', is => 'ro' );
after 'foo' => sub {
my $self = shift;
say 'Got ' . $self->foo;
}
结果是一个糟糕的无限循环。
->foo()
- after 修饰符执行并调用
->foo
->foo()
- after 修饰符执行并调用
->foo
- 无限循环
这是一个大多数人认为可行的示例,但实际上不行:每个人似乎都必须尝试一次的拙劣解决方案。请注意,您永远不应该这样做![1]
package Foobar;
use Data::Dumper;
use Moose;
sub method {
my ( $self, $ref ) = @_;
print Dumper [ 'method', $ref ];
};
sub modifier {
my ( $self, $ref ) = @_;
print Dumper [ 'modifier before', $ref ];
$ref->[0] = 'hax3d';
print Dumper [ 'modifier after', $ref ];
}
before 'method' => \&modifier;
package main;
my $m = Foobar->new;
$m->method( ['foo'] );
返回
$VAR1 = [ 'modifier before', [ 'foo' ] ]; $VAR1 = [ 'modifier after', [ 'hax3d' ] ]; $VAR1 = [ 'method', [ 'hax3d' ] ];
您可能认为这可行,因为您可以将修改方法添加到方法中。但是请注意,使用这种技术会在您传递非引用时产生巨大差异。
package Foobar;
use Data::Dumper;
use Moose;
sub method {
my ( $self, $scalar ) = @_;
print Dumper [ 'method', $scalar ];
};
sub modifier {
my ( $self, $scalar ) = @_;
print Dumper [ 'modifier before', $scalar ];
$scalar = 'bar';
print Dumper [ 'modifier after', $scalar ];
}
before 'method' => \&modifier;
package main;
my $m = Foobar->new;
$m->method( 'foo' );
$VAR1 = [ 'modifier before', 'foo' ]; $VAR1 = [ 'modifier after', 'bar' ]; $VAR1 = [ 'method', 'foo' ];
几乎肯定不是您想要的?[2] 别担心,现在您应该了解该怎么做。
Moose 之道™ 很简单,使用更合适的 around
。Moose 使您能够直接明确地表达您的意图。使用 around
,您的修饰符将获得:(a)所需方法的名称,(b)对 self 的引用,以及(c)发送给该函数的参数。然后,您可以 $self->$sub( @args )
如果您想调度该函数,或者完全重写或停止调用。
package Foobar;
use Data::Dumper;
use Moose;
sub method {
my ( $self, $scalar ) = @_;
print Dumper [ 'method', $scalar ];
};
sub modifier {
my ( $sub, $self, @args ) = @_;
print Dumper [ 'modifier', $sub, \@args ];
$self->$sub( @args );
}
around 'method' => \&modifier;
package main;
my $m = Foobar->new;
$m->method( 'foo' );
返回以下内容
$VAR1 = [ 'modifier', sub { "DUMMY" }, [ 'foo' ] ]; $VAR1 = [ 'method', 'foo' ];