我想在我的课程中为一些方法应用一个Moose'fake'方法修饰符。我想在角色中提供修饰符方法。我可以这样做:
package MyApp::Role;
use Moose::Role
before [qw(foo bar)] => sub {
...
};
package MyApp;
use Moose;
with (MyApp::Role);
sub foo { ... }
sub bar { ... }
sub baz { ... } # this method is unaffected
但是,必须维护角色中的相关方法列表将其与消费类联系起来,这似乎是错误的。我想以更聪明的方式做到这一点,比如方法属性:
package MyApp;
use Moose;
with (MyApp::Role);
sub foo :SomeFlag { ... }
sub bar :SomeFlag { ... }
sub baz { ... } # this method is unaffected
我不熟悉如何识别方法属性或如何动态地将方法修饰符应用于它们。
或者,也许有更好的方法可以做到这一点?
答案 0 :(得分:5)
让我们使用Attribute::Handlers
- 这是一种使用属性的相当明智的方法。我们必须在基类中定义一个函数,它本身具有属性:ATTR(CODE)
。这需要一些论据:
ANON
。所以我们可以做的是编写一个应用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
)。
输出:
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!