Is it possible to replace a method of a Moose object at runtime ?
By looking at the source code of Class::MOP::Method
(which Moose::Meta::Method
inherits from) I concluded that by doing
$method->{body} = sub{ my stuff }
I would be able to replace at runtime a method of an object. I can get the method using
$object->meta->find_method_by_name(<method_name>);
However, this didn't quite work out.
Is it conceivable to modify methods at run time? And, what is the way to do it with Moose?
Sinan's idea is a great start.
But with an little extra tweak, you can make using your method accessor just like using a normal method.
The two methods in
Frob
are very similar.frobit
passes all arguments, including the invocant to the code ref.goto_frob
passes all arguments, including the invocant to the code ref, and replacesgoto_frob
's stack frame with the code refs.Which to use depends on what you want in the stack.
Regarding munging the body storage of a
Class::MOP::Method
object, like so$method->{body} = sub { 'foo' }
:It's never a good idea to violate encapsulation when you are doing OOP. Especially not when you are working with complex object systems like Moose and Class::MOP. It's asking for trouble. Sometimes, there is no other way to get what you want, but even then, violating encapsulation is still a bad idea.
Using the previously mentioned
MooseX::SingletonMethod
you can replace an objects method.For example:
Also see this SO answer to What should I do with an object that should no longer be used in Perl?, which shows how this can be achieved using Moose roles.
/I3az/
Moose or not, that does not sound like a good idea.
Instead, design your object to have an accessor for the method. For example, users of your class can use
My::Frobnicator->frobnicator->()
to get and invoke thefrobnicator
method and useMy::Frobnicator->frobnicator(sub { } )
to set it.