I'm trying to deep copy an object which holds a 3D array. But it isn't working as expected.
class A
def initialize
@a = [[[1]], [[2]]]
end
def modify3D
@a[0][0] = @a[1][0]
end
def modify2D
@a[0] = @a[1]
end
def dup
copy = super
copy.make_independent!
copy
end
def make_independent!
@a = @a.dup
end
def show
print "\n#{@a}"
end
end
a = A.new
b = a.dup
#a.modify2D
b.show
a.modify3D
b.show
In this case b is changed by the modify3D call on a.
[[[1]], [[2]]]
[[[2]], [[2]]]
If I uncomment modify2D line everything works fine.
[[[1]], [[2]]]
[[[1]], [[2]]]
Could someone pls explain what is happening here?
Your copy isn't deep enough. Array#dup only duplicates the array itself, not the array elements. You end up with two different arrays that still share the same elements.
In this answer I showed how to use marshaling to do a deep copy. This method does all the work:
deep_copy works for any object that can be marshaled. Most built-in data types (Array, Hash, String, &c.) can be marshaled. Any object which instance variables can be marshaled can itself be marshaled.
Having defined deep_copy, then replace this line:
with this:
and it ought to work as you expect.