Как сделать отдельную копию объекта в Perl 6?

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


по умолчанию 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).