Ruby 更改克隆对象的值

Ruby 更改克隆对象的值,ruby,arrays,Ruby,Arrays,我有一个对象,它有一个名为my\u array的实例变量数组。我通过attr\u访问器声明它 my_object.my_array = [1,2,3] # <= I don't know the max size of my_array(it can be dynamic) 迭代未正确迭代。my_object.my_array的大小是3,那么它应该迭代三次,但不是,它只迭代一次。我相信这是因为新的\u对象.my\u array.clear,但是我从我的\u对象克隆了它,那么为什么会发生这

我有一个对象,它有一个名为
my\u array
的实例变量数组。我通过
attr\u访问器
声明它

my_object.my_array = [1,2,3] # <= I don't know the max size of my_array(it can be dynamic)

迭代未正确迭代。
my_object.my_array
的大小是3,那么它应该迭代三次,但不是,它只迭代一次。我相信这是因为
新的\u对象.my\u array.clear
,但是我从
我的\u对象
克隆了它,那么为什么会发生这种情况呢

问题是,
clone
将生成浅克隆,而不是深克隆。换句话说,
my_array
是一个引用,克隆的实例引用内存中的同一个数组。考虑:

class MyClass
  attr_accessor :my_array
end

a = MyClass.new
a.my_array = [1, 2, 3]
a.my_array
#=> [1, 2, 3]

b = a.clone
b.my_array.push(4)
b.my_array
#=> [1, 2, 3, 4]
a.my_array              # also changed!
#=> [1, 2, 3, 4]
为了解决此问题,您需要扩展
initialize\u copy
方法来克隆阵列:

class MyClass
  attr_accessor :my_array

  def initialize_copy(orig)
    super
    self.my_array = orig.my_array.clone
  end
end

a = MyClass.new
a.my_array = [1, 2, 3]
a.my_array
#=> [1, 2, 3]

b = a.clone
b.my_array.push(4)
b.my_array
#=> [1, 2, 3, 4]
a.my_array              # did not change, works as expected
#=> [1, 2, 3]

指定一个数组时,它只复制引用,并且两个数组都指向同一引用, 因此,当您打印其中一项时,其中一项的更改会反映出来:

orig_array = [1,2,3,4]<br>
another_array = orig_array

puts orig_array.unshift(0).inspect
puts another_array.inspect
为了避免这种情况,您可以使用封送处理从原始数组复制,而不会影响复制到的对象。 原始数组中的任何更改都不会更改将其复制到的对象

orig_array = [1,2,3,4]
another_array = Marshal.load(Marshal.dump(orig_array))

puts orig_array.unshift(0).inspect
puts another_array.inspect
哪些产出:

[0, 1, 2, 3, 4]
[0, 1, 2, 3, 4]
[0, 1, 2, 3, 4]
[1, 2, 3, 4]

非常感谢你的建议,真的很有帮助。
[0, 1, 2, 3, 4]
[1, 2, 3, 4]