【问题标题】:How to make a separate copy of an object in Perl 6?如何在 Perl 6 中制作对象的单独副本?
【发布时间】:2018-10-08 17:52:18
【问题描述】:

我不完全理解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]

【问题讨论】:

    标签: clone deep-copy raku shallow-copy


    【解决方案1】:

    Mu 继承的默认clone 是浅的,如文档所述。这意味着它只会复制对象本身,而不是对象引用的任何内容。可以覆盖 clone 以获得您喜欢的语义,这可能是最好的做法。

    在执行此操作时要知道的一件有用的事情是clone 采用命名参数并使用它们分配给克隆对象的属性。这是值得知道的,因为:

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

    因此对于问题中的情况,写作:

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

    将导致输出 [1 2] 可能符合预期。它是如何工作的?

    • |%_ 只是将任何调整传递给指定的此 clone 方法的调用者
    • :@!aa => @!a 的缩写
    • callwith 调用继承的 clone(在本例中来自 Mu
    • 在目标对象中的@!a 上使用赋值而非绑定语义(就像在对象构造期间一样),从而生成数组的副本

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

    【讨论】:

    • 如果class A 也是has @.b,我也应该加上:@!b 吗?那么,覆盖clone() 我应该明确处理所有可变属性吗?
    • @EugeneBarsky 是的,这是正确的;对于数组和散列,只需像callsame(:@!a, :%!b, ..., |%_) 一样列出它们。
    猜你喜欢
    • 2010-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-28
    • 2013-05-17
    • 1970-01-01
    相关资源
    最近更新 更多