Я пытаюсь придерживаться опубликованного 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:: Модификаторы :
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?
Спасибо!