2010-03-12 19 views
6

¿Es posible reemplazar un método de un objeto Moose en el tiempo de ejecución? Al mirar el código fuente de Class::MOP::Method (que hereda de Moose::Meta::Method) llegué a la conclusión de que al hacerlo¿Cómo se reemplaza un método de un objeto Moose en tiempo de ejecución?

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

Me gustaría ser capaz de reemplazar en tiempo de ejecución de un método de un objeto. puedo conseguir el método que utiliza

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

Sin embargo, estas consideraciones no eran bastante trabajo fuera.

¿Es concebible modificar los métodos en tiempo de ejecución? Y, ¿cuál es la manera de hacerlo con Moose?

Respuesta

4

Alce o no, eso no parece una buena idea.

En su lugar, diseñe su objeto para tener un descriptor de acceso para el método. Por ejemplo, los usuarios de su clase pueden usar My::Frobnicator->frobnicator->() para obtener e invocar el método frobnicator y usar My::Frobnicator->frobnicator(sub { }) para configurarlo.

+1

Sinan muy buena idea :) gracias – xxxxxxx

4

La idea de Sinan es un gran comienzo.

Pero con un poco de ajuste adicional, puede hacer que use su método de acceso al igual que con un método normal.

#!/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; 
    } 

} 

los dos métodos en Frob son muy similares.

  • frobit pasa todos los argumentos, incluido el invocante al código ref.
  • goto_frob pasa todos los argumentos, incluido el invocant al código ref, y reemplaza el marco de pila goto_frob con el código refs.

Cuál usar depende de qué usted quiere en la pila.


En cuanto munging el almacenamiento corporal de un objeto Class::MOP::Method, al igual que $method->{body} = sub { 'foo' }:

Nunca es una buena idea para violar la encapsulación cuando usted está haciendo programación orientada a objetos. Especialmente cuando trabajas con sistemas de objetos complejos como Moose y Class :: MOP. Está pidiendo problemas. A veces, no hay otra forma de obtener lo que quieres, pero aun así, violar la encapsulación sigue siendo una mala idea.

3

Utilizando el previously mencionado MooseX::SingletonMethod puede reemplazar un método de objetos.

Por ejemplo:

{ 
    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 

Véase también esta respuesta SO a What should I do with an object that should no longer be used in Perl?, que muestra cómo esto puede lograrse usando papeles alces.

/I3az/

Cuestiones relacionadas