2010-08-21 8 views
6

Tengo un objeto Moose:clonación profunda objeto alces con atributos que son arrayref [Objeto] y set :: Object

class My::Game { 
    has 'players' => (isa => 'Set::Object', ...) 
    has 'action_sequence' => (isa => 'ArrayRef[My::Game::Action]', ...) 
} 

Ahora quiero ser capaz de clonar este objeto con una llamada como $game2 = $game->clone; ¿Cómo lo clono profundamente para que se clonen los objetos en ArrayRef? Y más complicado, el Set::Object?

Miré MooseX::Clone, pero no estoy seguro de cómo aplicarlo a este caso. El código de ejemplo sería apreciado.

Gracias!

Respuesta

2

Resulta que simplemente agregando el rol MooseX::Clone para la clase proporciona un método clone() que recursivamente clona atributos.

  • Para atributos hashref/arrayref, copia estructuras.
  • Para los escalares (incluidas las referencias) simplemente hace una copia superficial de la referencia.
  • Si agrega traits => ['Clone'] al atributo, clonará recursivamente el atributo llamando al clone() en el valor del atributo.

Para apoyar la clonación Set::Object, terminé creando un rasgo denominado CloneByCoercion subclasificando el rasgo Clone, parametrizada con el tipo de coaccionar a/desde antes de la clonación.

Así que para usarlo, escribí:

has 'blah' => (isa => 'Set::Object', is => rw, 
    traits => ['CloneByCoercion' => {to=>'ArrayRef'}] 
); 

MooseX::Types::Set::Object proporciona coacciones hacia y desde arrayref (aunque necesitaba para arreglar un error en ella: la coacción a arrayref debe devolver una referencia, no una lista)

También modifiqué MooseX::Clone para mantener un hash visto por los objetos, de modo que sea compatible con la clonación de estructuras de objetos interconectados con referencias circulares.

Eventualmente voy a poner todo esto en CPAN o enviar parches a los módulos.

5

No he utilizado ninguna de las piezas aquí (MooseX::Clone, MooseX::Compile y Set::Object), así que aquí es sólo un esbozo de donde me gustaría empezar, desde mi revisión de la documentación y el conocimiento general de la arquitectura Moose:

  • MooseX :: Clone le da a su objeto un método clone(), que luego llamará a clone() en cada uno de sus atributos con el rasgo 'Clonar'.
  • tanto, es necesario añadir un método clone() para ambos de sus atributos ...
  • Sería un ambicioso esperanza de que MooseX :: Clone puede manejar native attribute arrayrefs, pero ya que probablemente no lo hace, puede llegar a ampliar esa función usted mismo (es decir, si 'action_sequence' tiene la opción traits => ['Array'], es lo suficientemente inteligente como para que el método de clonación se defina realmente a través de handles => { clone => [ 'map', 'clone' ] }; es decir, clone el atributo llamando a clone() en cada uno de los elementos) - Aquí es probable que envíe su primer parche
  • Set::Object La documentación sugiere que puede clonar objetos de manera confiable con Storable::dclone (que usted debería verificar y pulir el autor y/o proporcionar parches si no es correcto)
  • y ahora necesita agregar un método clone() al atributo Establecer :: Objeto, que los documentos sugieren que usted haga con MooseX::Compile (y aquí es donde debe ir en irc.perl.org #moose y darnos un golpe por golpe de su progreso, para que podamos hacer un documental al respecto más adelante) :)
+0

Creo que solo necesita usar el rasgo 'StorableClone' en el atributo Establecer :: Objeto; que debería usar automáticamente 'dclone' en él. (StorableClone es parte de MooseX :: Clone). – cjm

Cuestiones relacionadas