2014-09-23 77 views
0

我有一个对象,它有一个名为my_array的实例变量数组。我通过attr_accessor宣布它。更改克隆对象的值

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只有一个元素。该元素中的值是来自my_array的元素(来自my_object)的每个值。因为my_array的大小是动态的,所以我想我需要通过each来重复它。

这里是我的尝试:

my_object.my_array.each do |element|   # <= my_object is a special object 
    new_object = nil unless new_object.nil? 
    new_object = my_object.clone # <= I create new object with same class with my_object 
    new_object.my_array.clear # <= clear all element inside it. 
    new_object.my_array.push(element) # assign element value to the first element. 
    # rest of code # 
    new_object = nil 
end 

迭代不正确的迭代。 my_object.my_array的大小是3,那么它应该迭代三次,但不是,它只是迭代一次。我相信这是因为new_object.my_array.clear,但我从my_object克隆它,为什么发生这种情况?

回答

0

问题是,那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_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] 
+0

哦,你是让我的日子,我太感谢你了:) – LuminaChen 2014-09-23 16:03:18

1

当你将一个阵列,它只是复制引用,他们都点以相同的参考, 所以在一个变化体现在打印时其中一方:

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

puts orig_array.unshift(0).inspect 
puts another_array.inspect 

,输出:

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

为了避免这种情况,您可以使用Marshal从原始数组中复制而不影响其复制到的对象。 原始数组中的任何更改都不会更改其复制到的对象。

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] 
[1, 2, 3, 4] 
+0

非常感谢你的意见,really2很有帮助。 – LuminaChen 2014-09-25 17:09:36