Ruby中如何複製對象 (deep clone)(轉載)

Ruby中如何複製對象 (deep clone)

用Ruby複製一個對象(object)也許沒有你想像的那麼容易. 今天我google了半天, 作個總結吧.
先從最簡單的開始, b = a 是複製嗎? 看代碼說話:ruby

a= [0,[1,2]]
b=a
b[0]=88
b[1][0]=99
b 
=> [88, [99, 2]]
a 
=> [88, [99, 2]]

從上面代碼發現, 一但修改b, 原來的a也同時被改變了. 甚至:jsp

b.equal?(a)
=> true

原來b跟a根本就是同一個object, 只是馬甲不同罷了. 因此b = a不是複製.
那 b = a.dup呢??google

仍是看代碼:code

a= [0,[1,2]]
b=a.dup
b[0]=88
b[1][0]=99
b
=> [88, [99, 2]]
a
=> [0, [99, 2]]

狀況彷佛有所好轉, 在修改b後, a仍是有一部分被修改了.(0沒有變,但原來的1變成了99).
因此dup有時候是複製(如在Array只有一級時), 但有時不是複製哦.對象

再來一個, b = a.clone呢? 上代碼:get

a= [0,[1,2]]
b=a.clone
b[0]=88
b[1][0]=99
b
=> [88, [99, 2]]
a
=> [0, [99, 2]]

狀況幾乎跟dup如出一轍. 因此clone也不必定能夠相信哦!
原來ruby中的dup和clone都是shallow複製, 只針對object的第一級屬性.
汗, 難道在Ruby中沒有辦法複製對像嗎? 也不徹底是, 看這個:class

a= [0,[1,2]]
b=Marshal.load(Marshal.dump(a))
b[0]=88
b[1][0]=99
b
=> [88, [99, 2]]
a= [0,[1,2]]
=> [0, [1, 2]]

修改b後a沒有被改變!!! 彷佛終於成功找到複製的辦法了!!!
爲何要加"彷佛"呢? 由於有些object是不能被Marshal.dump的.如:thread

t=Object.new
def t.test; puts ‘test’ end
Marshal.dump(t)
TypeError: singleton can’t be dumped
from (irb):59:in `dump’
from (irb):59

更完善的複製方案能夠考慮給ruby增長一個deep clone功能, 能夠參考如下連接:
http://d.hatena.ne.jp/pegacorn/20070417/1176817721
http://www.artima.com/forums/flat.jsp?forum=123&thread=40913
好了, 複製這個小問題, 沒想到也能引出這麼長的文章來, 沒想到吧?test

忘記原文地址了,若有侵權,請告知!object

相關文章
相關標籤/搜索