Каков наилучший способ назначить тело метода во время построения при использовании Moose? - PullRequest
3 голосов
/ 14 декабря 2010

Я использую Moose (в частности, MooseX::Declare) для создания объекта итератора, Iter, который имеет метод next, который продвигает состояние и возвращает 0 или 1, как требуется для использования вwhile заявление.Проблема, с которой я сталкиваюсь, заключается в том, что в зависимости от существования одного из параметров конструкции, next необходимо выполнить два совершенно разных набора операций.На мой взгляд, у меня есть пять вариантов:

  1. если ... то в next метод
  2. подкласс
  3. отправка хеша
  4. манипулирование таблицей символов
  5. помещать методы в разные модули и загружать требуемый один во время сборки

Number 1 просто любитель.

Номер 2 , я полагаю, является правильным ООП-способом.Я не возражаю против этого, но кажется немного излишним просто отменить один метод.

Я часто использовал Номер 3 в прошлом, когда работал процедурно или псевдо-функционально, и это то, что я делаю сейчас.

Номер 4 , как мы все знаем, чревато опасностью, и я ничего не знаю о Moose Guts, чтобы захотеть начать бездельничать, когда в этом нет необходимости.

Последний элемент, номер 5 , мне кажетсябыть самым разумным (и Perlish), но, как и номер 2, это слишком много работы.Мне действительно интересно, есть ли пятый способ, который я не рассматривал, такой как подключение к метаклассу или, возможно, достаточно разумный MooseX модуль.

Ответы [ 2 ]

10 голосов
/ 14 декабря 2010

Передайте свой «следующий» подреф в конструктор и сохраните его в атрибуте:

has next => (
    isa => 'CodeRef',
    required => 1,
    traits => ['Code'],
    handles => { next => 'execute_method' },
);

С помощью обработчика «execute_method», предоставляемого чертой нативного атрибута «Код» ,Вы можете вызвать метод 'next' как обычный метод, и он найдет тело подрефера в атрибуте.

Если вы хотите предварительно определить тело (я) подрефера и решить во время построения, какую версию использовать, вы можете установить значение 'next' в сабвуфере в соответствии с другими условиями объекта:

has next => (
    # ...
    lazy => 1,
    default => sub {
         my $self = shift;
         return sub { ... } if $self->some_condition;
         # etc etc...
    },
);
0 голосов
/ 15 декабря 2010

Другим вариантом является динамическое применение роли:

package Iter;
use Moose;
use Moose::Util qw(apply_all_roles);

has next_role => (is => 'ro');

sub BUILD {
    my $self = shift;
    apply_all_roles($self, $self->next_role);
}
...