Как я составляю существующую роль Американского лося в класс во времени выполнения?

Скажите, что я определяю краткий обзор Мой:: Объектные и конкретные ролевые реализации Мой:: Объект:: TypeA и Мой:: Объект:: TypeB. По причинам пригодности для обслуживания я хотел бы не иметь hardcoded таблицу, которая смотрит на тип объекта и применяет роли. Как пример DWIMmy, я ищу что-то вдоль этих строк в Моем:: Объект:

has => 'id' (isa => 'Str', required => 1);

sub BUILD {
  my $self = shift;

  my $type = $self->lookup_type(); ## Returns 'TypeB'
  {"My::Object::$type"}->meta->apply($self);
}

Разрешение мне получить Мой:: Объект с Моим:: Объект:: роль TypeB, примененная путем выполнения следующего:

my $obj = My::Object(id = 'foo')

Это собирается сделать то, что я хочу, или я на совершенно неправильной дорожке?

Править: Я упростил это слишком много; я не хочу должным быть знать тип, когда я инстанцирую объекта, я хочу объект определить его тип и применить методы корректной роли соответственно. Я отредактировал свой вопрос сделать это более ясным.

6
задан Oesor 8 June 2010 в 20:12
поделиться

3 ответа

Вы пробовали?

$perl -Moose -E'
     sub BUILD { my ($self, $p) = @_; my $role = qq[Class::$$p{role}]; $role->meta->apply($self) };
     package Class::A; use Moose::Role; has a => (is => q[ro], default => 1);
     package main; say Class->new(role => q[A])->dump'

Выдает:

$VAR1 = bless( {
             'a' => 1
           }, 'Class::MOP::Class::__ANON__::SERIAL::1' );

Похоже, это то, что вы хотите. Очищенный код в вызове oose.pm:

package Class; 
use Moose;
sub BUILD { 
    my ($self, $p) = @_;
    my $role = qq[Class::$$p{role}];
    $role->meta->apply($self);
}

package Class::A;
use Moose::Role;

has a => ( is => 'ro', default => 1 );

package main;
Class->new(role => 'A');
7
ответ дан 9 December 2019 в 20:40
поделиться

После обновления вопроса я дам ему еще один взлом: with () - это просто вызов функции.

package Class;
use Moose;

BEGIN {
  with ( map "MyObject::$_", qw/TypeA TypeB/ );
}

Кроме того, вы можете ссылаться на текущий пакет с помощью константы perl __ PACKAGE __ .

1
ответ дан 9 December 2019 в 20:40
поделиться

Используйте MooseX::Traits, он превратит вашу роль в trait, который можно применять во время выполнения, затем вы просто вызовете:

   # Where Class is a class that has `use MooseX::Traits`;
   # And TypeB is a simple role
   Class->new_with_traits( traits => [qw/TypeB/] )

   # or even the new, and now preferred method.
   Class->with_traits('TypeB')->new();
4
ответ дан 9 December 2019 в 20:40
поделиться
Другие вопросы по тегам:

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