2010-06-08 8 views
6

Digamos que defino un resumen My :: Object y las implementaciones concretas de roles My :: Object :: TypeA y My :: Object :: TypeB. Por motivos de mantenimiento, me gustaría no tener una tabla codificada que examine el tipo de objeto y aplique roles. Como ejemplo DWIMmy, estoy buscando algo en este sentido en mi :: Objeto:¿Cómo compongo una función Moose existente en una clase en tiempo de ejecución?

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

sub BUILD { 
    my $self = shift; 

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

Dejando a conseguir un objeto con Mi :: :: Mi papel Objeto :: TypeB aplicado de la siguiente manera:

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

¿Esto va a hacer lo que quiero o estoy en la pista completamente equivocada?

Editar: He simplificado esto demasiado; No quiero tener que saber el tipo cuando crea una instancia del objeto, quiero que el objeto determine su tipo y aplique los métodos de la función correcta de manera apropiada. He editado mi pregunta para aclarar esto.

Respuesta

7

¿Lo has probado?

$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' 

Rendimiento:

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

Esto parece ser lo que quieres. Limpió el código en la llamada oose.pm es:

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'); 
+0

No, no lo hice. Era más una pregunta sobre prácticas recomendadas que me aseguraba de haber entendido correctamente la documentación de meta> y que no estaba tomando el camino equivocado. – Oesor

+0

Moose, y Perl en general es muy bueno acerca de ser un lenguaje experimental. Si tiene una pregunta, pruébelo y vea cuáles son los resultados. Si no comprende los resultados * entonces * pregunte ... se ahorrará mucho tiempo esperando que alguien más confirme/niegue su hipótesis. – perigrin

4

Uso MooseX::Traits, que a su vez su papel en un rasgoque se puede aplicar en tiempo de ejecución, a continuación, que acaba de llamar:

# 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(); 
+0

He editado mi pregunta para aclarar mi pregunta. Por lo que puedo decir, MooxeX :: Traits requiere que el tipo sea conocido en la instanciación de objetos. Quiero que el objeto determine su tipo y aplique el rol requerido, en lugar de requerir que forme parte de la API. – Oesor

1

Después de la actualización pregunta voy a darle otra oportunidad: es with() solo una llamada de función.

package Class; 
use Moose; 

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

Además, se puede hacer referencia al paquete actual con la constante __PACKAGE__ Perl.

Cuestiones relacionadas