我不太明白the docs ,所以我尝试了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]
最佳答案
从 Mu
继承的默认 clone
是浅层的,如文档所述。这意味着它只会复制对象本身,而不复制对象引用的任何内容。可以重写clone
以获得您喜欢的语义,这可能是这里最好的选择。
执行此操作时需要了解的一件有用的事情是 clone
接受命名参数并使用它们分配给克隆对象的属性。这是值得了解的,因为:
- 应确保在重写
clone
时处理此问题,以避免使用此功能的重写clone
方法的用户感到意外 - 在重写
clone
时可以使用它来简洁地选择克隆特定数组或哈希属性
因此,对于问题中的情况,写作:
class A {
has @.a;
method clone() {
callwith(:@!a, |%_)
}
}
将产生预期的输出[1 2]
。它是如何工作的?
- |%_ 只是传递此
克隆
方法的调用者指定的任何调整 :@!a
是a => @!a
的缩写
callwith
调用继承的克隆
(在本例中来自Mu
)- 目标对象中的
@!a
使用赋值而非绑定(bind)语义(就像在对象构造期间一样),从而生成数组的副本
此快捷方式也适用于哈希属性。对于包含另一个对象的属性,它看起来像 callsame(x => $!x.clone)
。
关于clone - 如何在 Perl 6 中创建对象的单独副本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50069947/