Как сделать отдельную копию объекта в Perl 6? - PullRequest
0 голосов
/ 27 апреля 2018

Я не совсем понимаю документы , поэтому я попробовал 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]

1 Ответ

0 голосов
/ 27 апреля 2018

Значение по умолчанию clone, унаследованное от Mu, является мелким, как описано в документации. Это означает, что он будет копировать только сам объект, но не все, на что ссылается объект. Можно переопределить clone, чтобы иметь предпочитаемую семантику, что, вероятно, лучше всего сделать здесь.

При этом полезно знать, что clone принимает именованные параметры и использует их для назначения свойств клонированного объекта. Это стоит знать, потому что:

  • Нужно обязательно учитывать это при переопределении clone, чтобы избежать неожиданностей для пользователей переопределенного метода clone, которые используют эту функцию
  • Это можно использовать при переопределении clone, чтобы кратко включить клонирование определенного массива или хеш-атрибута

Таким образом, для рассматриваемого случая пишем:

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

Результатом будет [1 2], как и предполагалось. Как это работает?

  • |% _ просто передает любые изменения, вызывающие этот clone метод, указанный
  • :@!a - это сокращение от a => @!a
  • callwith вызывает унаследованный clone (от Mu в данном случае)
  • Назначение, без привязки, семантика используется на @!a в целевом объекте (так же, как и при построении объекта), в результате чего получается копия массива

Этот ярлык работает и для хеш-атрибутов. Для атрибута, содержащего другой объект, он будет выглядеть как callsame(x => $!x.clone).

...