2010-03-12 5 views
6

Est-il possible de remplacer une méthode d'un objet Moose lors de l'exécution? En regardant le code source de Class::MOP::Method (qui hérite de Moose::Meta::Method) Je conclus qu'en faisantComment remplacer une méthode d'un objet Moose lors de l'exécution?

$method->{body} = sub{ my stuff } 

je serais en mesure de remplacer lors de l'exécution d'une méthode d'un objet. je peux obtenir la méthode utilisant

$object->meta->find_method_by_name(<method_name>); 

Cependant, cela ne fonctionne pas tout à fait.

Est-il concevable de modifier les méthodes lors de l'exécution? Et, quelle est la façon de le faire avec Moose?

Répondre

4

Moose ou pas, cela ne semble pas être une bonne idée.

Au lieu de cela, créez votre objet pour avoir un accesseur pour la méthode. Par exemple, les utilisateurs de votre classe peuvent utiliser My::Frobnicator->frobnicator->() pour obtenir et appeler la méthode frobnicator et utiliser My::Frobnicator->frobnicator(sub { }) pour le définir.

+1

Sinan très bonne idée :) merci – xxxxxxx

4

L'idée de Sinan est un bon début. Mais avec un petit ajustement supplémentaire, vous pouvez utiliser l'accesseur de votre méthode comme avec une méthode normale. Les deux méthodes dans Frob sont très similaires.

  • frobit passe tous les arguments, y compris le invocant à l'arbitre de code.
  • goto_frob passe tous les arguments, y compris l'invocant au code ref, et remplace la trame de pile goto_frob par les références de code.

La méthode à utiliser dépend de ce que vous voulez dans la pile.


En ce qui concerne le stockage munging du corps d'un objet Class::MOP::Method, comme si $method->{body} = sub { 'foo' }:

Il est jamais une bonne idée de violer l'encapsulation lorsque vous faites POO. Surtout pas quand vous travaillez avec des systèmes d'objets complexes comme Moose et Class :: MOP. C'est demander des ennuis. Parfois, il n'y a pas d'autre moyen d'obtenir ce que vous voulez, mais même alors, violer l'encapsulation est toujours une mauvaise idée.

3

En utilisant le previously mentionné MooseX::SingletonMethod vous pouvez remplacer une méthode d'objets.

Par exemple:

{ 
    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 

Voir aussi cette réponse SO à What should I do with an object that should no longer be used in Perl?, qui montre comment cela peut être réalisé en utilisant des rôles Moose.

/I3az/

Questions connexes