Как Вы заменяете метод объекта Американского лося во времени выполнения?

Действительно ли возможно заменить метод объекта Американского лося во времени выполнения? Путем рассмотрения исходного кода Class::MOP::Method (который Moose::Meta::Method наследовался), я завершил это путем выполнения

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

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

 $object->meta->find_method_by_name();

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

Действительно ли это мыслимо для изменения методов во время выполнения? И, что путь состоит в том, чтобы сделать это с Американским лосем?

6
задан hlt 22 August 2014 в 18:43
поделиться

3 ответа

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

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

4
ответ дан 9 December 2019 в 22:32
поделиться

Идея Синан - отличное начало.

Но с небольшой дополнительной настройкой вы можете использовать свой метод доступа точно так же, как и обычный метод.

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

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


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

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

4
ответ дан 9 December 2019 в 22:32
поделиться

Используя ранее упомянутый 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

Также см. Этот SO-ответ на Что мне делать с объектом, который больше не должен использоваться в Perl? , где показано, как этого можно достичь с помощью ролей Moose.

/ I3az /

3
ответ дан 9 December 2019 в 22:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: