如何在运行时将现有Moose角色组合成一个类?

Oes*_*sor 6 perl roles moose

假设我定义了一个抽象的My :: Object和具体的角色实现My :: Object :: TypeA和My :: Object :: TypeB.出于可维护性的原因,我希望没有一个硬编码表来查看对象类型并应用角色.作为一个DWIMmy示例,我在My :: Object中寻找这些行中的内容:

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

sub BUILD {
  my $self = shift;

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

让我通过执行以下操作来应用具有My :: Object :: TypeB角色的My :: Object:

my $obj = My::Object(id = 'foo')
Run Code Online (Sandbox Code Playgroud)

这会做我想做的事情还是在完全错误的轨道上?

编辑:我太简化了; 我不想在实例化对象时知道类型,我希望对象确定其类型并适当地应用正确的角色方法.我编辑了我的问题以使其更清楚.

per*_*rin 7

你试过吗?

$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'
Run Code Online (Sandbox Code Playgroud)

产量:

$VAR1 = bless( {
             'a' => 1
           }, 'Class::MOP::Class::__ANON__::SERIAL::1' );
Run Code Online (Sandbox Code Playgroud)

这似乎是你想要的.清理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');
Run Code Online (Sandbox Code Playgroud)