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

PBJ*_*PBJ 6 arrays perl clone moose

我有一个Moose对象:

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

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

我看过MooseX :: Clone,但我不清楚如何将它应用于这种情况.示例代码将不胜感激.

谢谢!

Eth*_*her 5

我没有使用过这里的任何一个部分(MooseX :: Clone,MooseX :: CompileSet :: Object),所以这里只是一个粗略的概述我从哪里开始,从我对文档和常识的回顾穆斯建筑:

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


PBJ*_*PBJ 2

事实证明,只需将MooseX::Clone角色添加到类中就可以提供一种clone()递归克隆属性的方法。

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

为了支持 cloning Set::Object,我最终创建了一个CloneByCoercion通过子类化特征来调用的Clone特征,并使用克隆之前强制转换的类型进行参数化。

因此,为了使用它,我写道:

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

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

我还进行了修改MooseX::Clone以保留对象可见的哈希值,以便它支持克隆具有循环引用的互连对象结构。

我最终会抽出时间将这些内容放在 CPAN 上或向模块提交补丁。