深度克隆具有ArrayRef [Object]和Set :: Object属性的Moose对象

时间:2010-08-21 07:17:16

标签: arrays perl clone moose

我有一个Moose对象:

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

现在我希望能够通过像$game2 = $game->clone;这样的调用来克隆这个对象。如何深度克隆它以便克隆ArrayRef中的对象?更巧妙的是,Set::Object

我看过MooseX::Clone,但我不清楚如何将它应用于此案例。示例代码将不胜感激。

谢谢!

2 个答案:

答案 0 :(得分:5)

我没有使用过此处的任何内容(MooseX::CloneMooseX::CompileSet::Object),所以这里只是我从哪里开始的大致轮廓,从我的评论Moose建筑的文献和一般知识:

  • MooseX :: Clone为您的对象提供clone()方法,然后使用'Clone'特征在每个属性上调用clone()。
  • 所以,你需要为你的两个属性添加一个clone()方法......
  • 这将是我雄心勃勃的希望 MooseX :: Clone可以处理native attribute arrayrefs,但由于它可能没有,你可以自己扩展该功能(即如果'action_sequence '有选项traits => ['Array'],它足够聪明,克隆方法实际上是通过handles => { clone => [ 'map', 'clone' ] }定义的 - 即通过在每个成员元素上调用clone()来克隆属性) - 这里很可能您将在哪里提交第一个补丁
  • Set::Object的文档建议您可以使用Storable::dclone可靠地克隆对象(您应该验证它们,如果不正确则鞭打作者和/或提供补丁)
  • 现在你需要将一个clone()方法添加到Set :: Object属性中,文档建议你使用MooseX::Compile(这里是你应该来的地方)irc.perl.org #moose并给我们一个逐步的进展,所以我们可以在以后制作一部关于它的纪录片:))

答案 1 :(得分:2)

事实证明,简单地将MooseX::Clone角色添加到类中会提供递归克隆属性的clone()方法。

  • 对于hashref / arrayref属性,它会复制结构。
  • 对于标量(包括引用),它只是执行引用的浅表副本。
  • 如果您向该属性添加traits => ['Clone'],它将通过在属性值上调用clone()来递归克隆该属性。

为了支持克隆Set::Object,我最终创建了一个名为CloneByCoercion的特征,通过继承Clone特征,在克隆之前使用类型进行参数化以强制进出/。

为了使用它,我写道:

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

MooseX::Types::Set::Object向ArrayRef提供强制攻击(尽管我需要修补其中的错误:对ArrayRef的强制应该返回引用,而不是列表)

我还修改了MooseX::Clone以保持对象看到的哈希值,以便它支持使用循环引用克隆相互链接的对象结构。

我最终会把这些东西放在CPAN上或者向模块提交补丁。