I don't fully understand the docs, so I've tried clone
, and it seems if there is an attribute of a mutable class, it can be changed in the new object using the old one (and that's what I don't want). How to make them (i.e. the copy and the original) fully separate?
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]
The default clone
inherited from Mu
is shallow, as documented. This means that it will only copy the object itself, but not anything the object references. It is possible to override clone
to have your preferred semantics, which is probably the best thing to do here.
One useful thing to know in doing this is that clone
takes named parameters and uses them to assign to properties of the cloned object. This is worth knowing because:
clone
, to avoid surprises to users of the overridden clone
method who use this featureclone
to succinctly opt in to cloning of a particular array or hash attributeThus for the case in the question, writing:
class A {
has @.a;
method clone() {
callwith(:@!a, |%_)
}
}
Will result in the output [1 2]
as presumably desired. How does it work?
clone
method specified:@!a
is short for a => @!a
callwith
calls the inherited clone
(from Mu
in this case)@!a
in the target object (just as during object construction), resulting in a copy of the arrayThis shortcut works for hash attributes too. For an attribute containing another object, it'd look like callsame(x => $!x.clone)
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With