用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