我有一个在其状态下嵌入数组的对象。我在对象实例上使用deep_dup
,但返回的对象引用与原始实例相同的数组对象,这不是我期望的。
以下是我的工作:
class A
def initialize(arr)
@arr = arr.deep_dup
end
attr_accessor :arr
end
a = A.new(['a', 'b', 'c'])
# => #<A:0x007fe6eb7ae458 @arr=["a", "b", "c"]>
b = a.deep_dup
# => #<A:0x007fe6f382ad20 @arr=["a", "b", "c"]>
b.arr[1] = 'e'
# => "e"
a
# => #<A:0x007fe6eb7ae458 @arr=["a", "e", "c"]>
b
# => #<A:0x007fe6f382ad20 @arr=["a", "e", "c"]>
a.arr.object_id
# => 70314884952600
b.arr.object_id
# => 70314884952600
我已阅读deep_dup
的文档,
deep_dup方法返回给定对象的深层副本。
我在做什么或理解错误?
答案 0 :(得分:1)
如果您在Object
deep_dup
的来源
def deep_dup duplicable? ? dup : self end
它只是调用dup
(默认情况下duplicable?
始终为true)。其中,对于数组,它在每个元素上调用deep_dup
:
def deep_dup map(&:deep_dup) end
Object
查看dup
(因为那是A
上最终被调用的内容):
生成obj的浅表副本 - 复制obj的实例变量,但不复制它们引用的对象。 dup复制obj的污点状态。
所以,为了让你的榜样有效,你需要这样的东西:
class A
attr_accessor :array
def initialize(array)
@array = array.deep_dup
end
def initialize_copy(copy)
copy.array = self.array.deep_dup
super
end
end
a = A.new(['a', 'b', 'c'])
b = a.deep_dup
b.array[1] = 'e'
puts a.inspect # => #<A:0x007f857be2f510 @array=["a", "b", "c"]>
puts b.inspect # => #<A:0x007f857be2f448 @array=["a", "e", "c"]>
puts a.array.object_id # => 70105642924 560 (spaces added for clarity)
puts b.array.object_id # => 70105642924 660
initialize_copy
方法在任何地方都没有详细记录,但dup
方法声明
此方法可能具有特定于类的行为。如果是这样,该行为将记录在类的#initialize_copy方法下。
因此,将其设置为自定义dup
流程的方式,而不会实际覆盖dup
和this文档(这是我可以找到的唯一真实文档方法)显示它只采用1参数,即副本