如何在Perl 6中制作对象的单独副本?

Eug*_*sky 8 clone deep-copy shallow-copy perl6

我不完全理解文档,所以我尝试过clone,似乎有一个可变类的属性,它可以在旧对象中使用旧对象进行更改(这就是我不想要的) .如何使它们(即副本和原件)完全分开?

class A {
  has @.a;
}

my A $x = A.new;
my A $y = A.new;

$x.a = 1, 2;

$y = $x.clone;

$x.a.push(4);
say $y.a; # [1 2 4]
Run Code Online (Sandbox Code Playgroud)

Jon*_*ton 9

正如文档所述,clone继承自的默认值Mu很浅.这意味着它只会复制对象本身,而不会复制对象引用的任何内容.可以覆盖clone以获得您的首选语义,这可能是最好的事情.

这样做的一个有用的事情是clone获取命名参数并使用它们来分配克隆对象的属性.这值得了解,因为:

  • 应该确保在覆盖时处理此问题clone,以避免clone使用此功能的被覆盖方法的用户感到意外
  • 可以在重写clone时简洁地选择克隆特定数组或散列属性

因此,对于问题中的案例,写作:

class A {
    has @.a;
    method clone() {
        callwith(:@!a, |%_)
    }
}
Run Code Online (Sandbox Code Playgroud)

将导致输出[1 2]大概是所希望的.它是如何工作的?

  • |%_只传递clone指定此方法的调用者的任何调整
  • :@!a 是的缩写 a => @!a
  • callwith调用继承的clone(Mu在这种情况下)
  • @!a在目标对象中使用赋值,而不是绑定,语义(就像在对象构造期间一样),从而产生数组的副本

此快捷方式也适用于哈希属性.对于包含另一个对象的属性,它看起来像callsame(x => $!x.clone).

  • @EugeneBarsky是的,这是正确的; 对于数组和哈希值,只需将它们列为`callsame(:@!a,:%!b,...,|%_)`. (2认同)