使用 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'
];