6

抽象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')

これは私が望むことをするつもりですか、それとも私は完全に間違った方向に進んでいますか?

編集:私はこれを単純化しすぎました。オブジェクトをインスタンス化するときにタイプを知る必要はありません。オブジェクトにタイプを判別させ、正しいロールのメソッドを適切に適用してもらいたいのです。これを明確にするために質問を編集しました。

4

3 に答える 3

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');
于 2010-06-08T20:19:58.937 に答える
4

を使用すると、役割が実行時に適用できる特性MooseX::Traitsに変わり、次のように呼び出すだけです。

   # 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();
于 2010-06-08T19:54:44.597 に答える
1

質問の更新後、別のクラックを付けます。これwith()は単なる関数呼び出しです。

package Class;
use Moose;

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

また、perl定数を使用して現在のパッケージを参照できます__PACKAGE__

于 2010-06-08T20:16:12.347 に答える