假设我定义了一个抽象的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);
}
通过执行以下操作,让我通过应用My :: Object :: TypeB角色来获取My :: Object:
my $obj = My::Object(id = 'foo')
这会做我想做的事情,还是我在完全错误的轨道上?
编辑:我对此进行了简化;我不想在实例化对象时知道类型,我希望对象确定其类型并适当地应用正确的角色方法。我编辑了我的问题以使其更清晰。
答案 0 :(得分: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'
收率:
$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');
答案 1 :(得分:4)
使用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();
答案 2 :(得分:1)
问题更新后我会再给它一个问题:with()
只是一个函数调用。
package Class;
use Moose;
BEGIN {
with ( map "MyObject::$_", qw/TypeA TypeB/ );
}
此外,您可以使用perl常量__PACKAGE__
引用当前包。