2010-03-12 3 views
6

Возможно ли заменить метод объекта Moose во время выполнения? Глядя на исходный код Class::MOP::Method (который наследуется от Moose::Meta::Method) я пришел к выводу, что, делаяКак вы заменяете метод объекта Moose во время выполнения?

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

я смог бы заменить во время выполнения метода объекта. я могу получить метод, используя

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

Однако это не совсем получилось.

Можно ли модифицировать методы во время выполнения? И каков способ сделать это с Мусом?

ответ

4

Лось или нет, это звучит не очень хорошая идея.

Вместо этого создайте свой объект для доступа к методу. Например, пользователи вашего класса могут использовать My::Frobnicator->frobnicator->(), чтобы получить и вызвать метод frobnicator и использовать My::Frobnicator->frobnicator(sub { }), чтобы установить его.

+1

Sinan очень хорошая идея :) спасибо – xxxxxxx

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 передает все аргументы, включая invocant к коду ref.
  • goto_frob передает все аргументы, включая invocant, в код ref, и заменяет стек стека goto_frob кодом кода ref.

Для использования зависит от того, что вы хотите в стеке.


Что касается munging хранения тела в Class::MOP::Method объекта, например, так $method->{body} = sub { 'foo' }:

Это никогда не является хорошей идеей, чтобы нарушить инкапсуляцию, когда вы делаете ООП. Особенно, когда вы работаете со сложными объектными системами, такими как Moose и Class :: MOP. Он просит неприятностей. Иногда нет другого способа получить то, что вы хотите, но даже тогда нарушение инкапсуляции по-прежнему является плохим.

3

Использование previouslyMooseX::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 

см Также этот SO ответ на What should I do with an object that should no longer be used in Perl?, который показывает, как это может быть достигнуто с помощью роли Moose.

/I3az/

Смежные вопросы