可能的原因紅寶石不包含深克隆具有與問題的複雜性有關。請參閱最後的註釋。
要生成一個將「深度複製」,「哈希」,「數組」和元素值的克隆,即,使每個元素的副本,在原來使得副本都會有相同的價值觀,但新的對象,你可以這樣做:如果你想重新定義Ruby的clone
方法的行爲
class Object
def deepclone
case
when self.class==Hash
hash = {}
self.each { |k,v| hash[k] = v.deepclone }
hash
when self.class==Array
array = []
self.each { |v| array << v.deepclone }
array
else
if defined?(self.class.new)
self.class.new(self)
else
self
end
end
end
end
,你可以它只是clone
而不是deepclone
(在3個地方),但我不知道如何重新定義Ruby的克隆行爲將影響Ruby庫或Ruby on Rails,因此Caveat Emptor。就我個人而言,我不能推薦這樣做。
例如:
a = {'a'=>'x','b'=>'y'} => {"a"=>"x", "b"=>"y"}
b = a.deepclone => {"a"=>"x", "b"=>"y"}
puts "#{a['a'].object_id}/#{b['a'].object_id}" => 15227640/15209520
如果你想你類deepclone得當,他們new
方法(初始化)必須能夠deepclone那個類的一個對象的標準方式,即如果第一個參數被給出,它被假定爲要被深度克隆的對象。
假設我們想要一個M類,例如。第一個參數必須是M類的可選對象。這裏我們有第二個可選參數z
來預先設置新對象中z的值。
class M
attr_accessor :z
def initialize(m=nil, z=nil)
if m
# deepclone all the variables in m to the new object
@z = m.z.deepclone
else
# default all the variables in M
@z = z # default is nil if not specified
end
end
end
的z
預組克隆這裏期間被忽略,但是你的方法可能有不同的行爲。這個類的對象將這樣創建:
# a new 'plain vanilla' object of M
m=M.new => #<M:0x0000000213fd88 @z=nil>
# a new object of M with m.z pre-set to 'g'
m=M.new(nil,'g') => #<M:0x00000002134ca8 @z="g">
# a deepclone of m in which the strings are the same value, but different objects
n=m.deepclone => #<M:0x00000002131d00 @z="g">
puts "#{m.z.object_id}/#{n.z.object_id}" => 17409660/17403500
當M級的對象是一個陣列的一部分:
a = {'a'=>M.new(nil,'g'),'b'=>'y'} => {"a"=>#<M:0x00000001f8bf78 @z="g">, "b"=>"y"}
b = a.deepclone => {"a"=>#<M:0x00000001766f28 @z="g">, "b"=>"y"}
puts "#{a['a'].object_id}/#{b['a'].object_id}" => 12303600/12269460
puts "#{a['b'].object_id}/#{b['b'].object_id}" => 16811400/17802280
注:
- 如果
deepclone
嘗試克隆對象它不以標準方式克隆自己,它可能會失敗。
- 如果
deepclone
試圖克隆一個可以以標準方式克隆自身的對象,並且如果它是一個複雜的結構,它可能(也可能會)對其本身進行淺層克隆。
deepclone
不會深入複製哈希中的密鑰。原因是他們通常不被視爲數據,但如果您將hash[k]
更改爲hash[k.deepclone]
,它們也將被深度複製。
- 某些元素值沒有
new
方法,如Fixnum。這些對象總是具有相同的對象ID,並且被複制,而不被克隆。
- 要小心,因爲當您進行深度複製時,在原始文件中包含相同對象的哈希或數組的兩部分將在深克隆中包含不同的對象。
謝謝,埃文!好東西,我很欣賞基準。 :) – mway 2011-06-03 23:15:34
嘿@Evan Pon,我在你的例子中添加了[MessagePack](http://msgpack.org/)。這是一個不錯的選擇。 – 2012-07-06 04:37:53
MessagePack看起來非常快(比我的機器上的Custom快2倍)。你能否用建議更新答案而不是元帥? – 2013-02-03 09:31:03