Идея Синана - прекрасное начало.
Но с небольшой дополнительной настройкой вы можете сделать это с помощью метода доступа к методу, как при использовании обычного метода.
#!/usr/bin/perl
use strict;
use warnings;
use Carp;
my $f = Frob->new;
$f->frob(
sub {
my $self = shift;
print "$self was frobbed\n";
print Carp::longmess('frob')
}
);
print "\nCall frob as normal sub\n";
$f->frobit;
print "\nGoto frob\n";
$f->goto_frob;
BEGIN {
package Frob;
use Moose;
has 'frob' => (
is => 'rw',
isa => 'CodeRef',
);
sub frobit {
&{$_[0]->frob};
}
sub goto_frob {
goto $_[0]->frob;
}
}
Два метода в Frob
очень похожи.
frobit
передает все аргументы, включая инвокант к коду ref.
goto_frob
передает все аргументы, включая инвокант в код ref, и заменяет кадр стека goto_frob
на код refs.
Что использовать, зависит от того, что вы хотите в стеке.
Относительно хранения тела объекта Class::MOP::Method
, вот так $method->{body} = sub { 'foo' }
:
Никогда не стоит нарушать инкапсуляцию, когда вы выполняете ООП. Особенно, если вы работаете со сложными объектными системами, такими как Moose и Class :: MOP. Это напрашивается на неприятности. Иногда нет другого способа получить то, что вы хотите, но даже тогда нарушать инкапсуляцию - все еще плохая идея.