我试图坚持使用已发布的API来动态修改Moo
中的方法,并且没有提出通用的解决方案。
首先,输入一些代码:
package R1 {
use Moo::Role;
sub r1 { say __PACKAGE__ }
}
package C1 {
use Moo;
sub c1 { say __PACKAGE__ }
}
use Scalar::Util qw[ blessed ];
use Moo::Role ();
my $c = C1->new;
Moo::Role->apply_roles_to_object( $c, 'R1' );
角色应用程序将以一种方法说明失败。
我尝试了两种方法。
第一个使用Class::Method::Modifiers:
use Class::Method::Modifiers qw[ install_modifier ];
install_modifier( blessed( $c ),
before => r1 =>
sub { say "BEFORE r1" }
);
$c->r1;
工作正常:
% perl test.pl
BEFORE r1
R1
Moo
内部_install_modifier
子例程的代码非常相似,但是还执行其他Moo
特定的动作,因此这种方法并不完全等效。
我尝试的下一种方法是直接使用before
可用的$c
修饰符,从而获得额外的Moo
特殊调味料:
$c->can('before')->( r1 => sub { say "BEFORE r1" } );
$c->r1;
但是...
% perl test.pl
The method 'r1' is not found in the inheritance hierarchy for class C1 at [...]/lib/site_perl/5.28.0/Class/Method/Modifiers.pm line 42.
Class::Method::Modifiers::install_modifier("C1", "before", "r1") called at /[...]/lib/site_perl/5.28.0/Moo/_Utils.pm line 44
Moo::_Utils::_install_modifier("C1", "before", "r1", CODE(0x5590bb800360)) called at [...]/lib/site_perl/5.28.0/Moo.pm line 84
Moo::before("r1", CODE(0x5590bb800360)) called at test.pl line 25
似乎修饰符是为原始C1
类生成的,并且在应用R1
角色时不会更新。以下令人震惊的骇客“修复”:
use Import::Into;
Moo->import::into( blessed $c );
$c->can('before')->( r1 => sub { say "BEFORE r1" } );
$c->r1;
结果为:
% perl test.pl
BEFORE r1
R1
那么,有没有办法仅使用已发布的Moo
API来实现我的目标?
谢谢!
答案 0 :(得分:1)
您可以通过应用其他角色来修改方法(除非您要处理属性,否则它甚至不必是Moo :: Role):
use Role::Tiny;
before r1 => sub { say "BEFORE r1" };
只需确保在组成r1方法的角色之后应用此角色,或者在角色中包含一个虚拟sub r1 {}
(如果已经存在,它将被忽略)。