让我们使用Attribute::Handlers
它——一种相当理智的使用属性的方法。我们必须在本身具有属性的基类中定义一个函数:ATTR(CODE)
。这需要一些参数:
- 子(或其他变量)来自的包。
- 一个 globref 或字符串
ANON
。
- 对值的引用(此处:coderef)。
- 属性的名称。
- 属性的可选数据。
- 调用属性的(编译)阶段。
- 声明 sub 的文件名。
- 声明 sub 的行号。
所以我们可以做的是编写一个应用程序的处理程序before
:
use strict; use warnings; use feature 'say';
BEGIN {
package MyRole;
use Moose::Role;
use Attribute::Handlers;
sub SomeFlag :ATTR(CODE) {
my ($package, $globref, $code, $attr, $data, $phase, $filename, $line) = @_;
ref($globref) eq 'GLOB'
or die "Only global subroutines can be decorated with :SomeFlag"
. " at $filename line $line.\n";
# use the MOP to install the method modifier
$package->meta->add_before_method_modifier(
*$globref{NAME} => sub {
warn "Just about to call a flagged sub!";
},
);
}
}
BEGIN {
package MyApp;
use Moose;
# important: SomeFlag must be available before the attrs are handled (CHECK phase)
BEGIN { with 'MyRole' };
sub foo :SomeFlag { say "Hi from foo sub!" }
sub bar :SomeFlag { say "Hi from bar sub!" }
sub baz { say "Hi from baz sub!" }
}
package main;
my $o = MyApp->new;
$o->$_ for qw/foo bar baz/;
我将所有这些都塞进了一个文件中,但这显然不是必需的(只需添加所需use
的 s)。
输出:
Just about to call a flagged sub! at so.pl line 16.
Hi from foo sub!
Just about to call a flagged sub! at so.pl line 16.
Hi from bar sub!
Hi from baz sub!