首页 文章

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

提问于
浏览
6

我有一个Moose对象:

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

现在我希望能够通过像_1793085这样的调用来克隆这个对象 . 如何深度克隆它以便克隆ArrayRef中的对象?更狡猾的是,Set::Object

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

谢谢!

2 回答

  • 2

    我没有使用过这里的任何部分(MooseX::CloneMooseX::CompileSet::Object),所以这里's just a rough outline of where I'开始,从我对Moose架构的文档和一般知识的评论开始:

    • MooseX :: Clone为您的对象提供clone()方法,然后使用'Clone' trait对每个属性调用clone() .

    • 所以,你需要为你的两个属性添加一个clone()方法......

    • 这将是我雄心勃勃的希望,MooseX :: Clone可以处理native attribute arrayrefs,但由于它可能没有't, you may get to extend that feature yourself (i.e. if ' action_sequence'选项 traits => ['Array'] ,因此克隆方法实际上是通过 handles => { clone => [ 'map', 'clone' ] } 定义的,这很聪明 - 即通过调用克隆属性每个成员元素上的clone()) - 这可能是您提交第一个补丁的地方

    • Set::Object的文档建议您可以使用Storable::dclone可靠地克隆对象(如果这不正确,您应该验证并鞭打作者和/或提供补丁)

    • 现在你需要将一个clone()方法添加到Set :: Object属性中,文档建议你使用MooseX::Compile(这里你应该来irc.perl.org #moose并给我们一个打击 - 你的进步受到了影响,所以我们可以稍后制作一部关于它的纪录片:)

  • 5

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

    • 对于hashref / arrayref属性,它复制结构 .

    • 对于标量(包括引用),它只是执行引用的浅表副本 .

    • 如果将 traits => ['Clone'] 添加到属性,它将通过在属性值上调用 clone() 来递归克隆该属性 .

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

    所以要使用它,我写道:

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

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

    我还修改了 MooseX::Clone 以保持对象看到的散列,以便它支持使用循环引用克隆互连对象结构 .

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

相关问题