是否可以在运行时替换Moose对象的方法?
通过查看Class::MOP::Method
(Moose::Meta::Method
继承自的)的源代码,我得出结论
$method->{body} = sub{ my stuff }
我可以在运行时替换对象的方法。 我可以使用
获取方法 $object->meta->find_method_by_name(<method_name>);
然而,这并没有成功。
是否可以在运行时修改方法?而且,用Moose做这件事的方法是什么?
答案 0 :(得分:4)
麋与否,这听起来不是一个好主意。
相反,将对象设计为具有该方法的访问器。例如,您班级的用户可以使用My::Frobnicator->frobnicator->()
来获取和调用frobnicator
方法,并使用My::Frobnicator->frobnicator(sub { } )
进行设置。
答案 1 :(得分:4)
思南的想法是一个很好的开始。
但是通过一些额外的调整,您可以像使用普通方法一样使用方法访问器。
#!/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
将所有参数传递给代码引用。goto_frob
将所有参数传递给代码引用,包括调用代码引用,并用代码引用替换goto_frob
的堆栈帧。使用哪种方法取决于您在堆栈中的需求。
关于修改Class::MOP::Method
对象的正文存储,如$method->{body} = sub { 'foo' }
:
在进行OOP时违反封装永远不是一个好主意。特别是在使用Moose和Class :: MOP等复杂对象系统时。这是在惹麻烦。有时,没有其他方法可以获得你想要的东西,但即便如此,违反封装仍然是一个坏主意。
答案 2 :(得分:3)
使用提到的previously MooseX::SingletonMethod
,您可以替换对象方法。
例如:
{
package Foo;
use MooseX::SingletonMethod;
sub foo { say 'bar' };
}
my $bar = Foo->new;
my $baz = Foo->new;
# replace foo method just in $baz object
$baz->add_singleton_method( foo => sub { say 'baz' } );
$bar->foo; # => bar
$baz->foo; # => baz
另见What should I do with an object that should no longer be used in Perl?的回答,其中显示了如何使用Moose角色实现这一目标。
/ I3az /