转自船长日志, 本文链接地址: http://www.cslog.cn/Content/ruby-deep-clone/
用Ruby复制一个对象(object)也许没有你想像的那么容易. 今天我google了半天, 做个总结吧.
先从最简单的开始, b = a 是复制吗? 看代码说话:
>> a= [0,[1,2]]
>> b=a
>> b[0]=88
>> b[1][0]=99
>> b
=> [88, [99, 2]]
>> a
=> [88, [99, 2]]
从上面代码发现, 一但修改b, 原来的a也同时被改变了. 甚至:
>> b.equal?(a)
=> true
原来b跟a根本就是同一个object, 只是马甲不一样罢了. 所以b = a不是复制.
那 b = a.dup呢?? 还是看代码:
>> 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呢? 上代码:
>> 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中没有办法复制对像吗? 也不完全是, 看这个:
>> 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的.如:
>> 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
好了, 复制这个小问题, 没想到也能引出这么长的文章来, 没想到吧?
分享到:
相关推荐
Ruby支持对象的克隆,`Object#clone`或`Object#dup`方法可以实现原型模式。 6. **适配器模式**:将一个类的接口转换成客户希望的另一个接口。Ruby的鸭子类型特性使得适配器模式尤为自然,只需确保对象响应所需的...
- **复制数组**:`clone`或`dup`可以创建数组的副本,避免原数组被修改。 ### 数组迭代 Ruby提供了许多迭代方法来处理数组中的每个元素,如`each`、`map`、`each_with_index`等。例如: ```ruby arr.each { |...
1. Object:所有Ruby对象的基类,包含了一些通用的方法,如`object_id`用于获取对象的唯一标识,`==`进行对象的比较,`clone`和`dup`用于创建对象的副本。 2. String:处理文本字符串的类,提供了丰富的字符串操作...
`dup` 和 `clone` 都可以用来复制字符串,但它们之间存在细微的区别。 #### 5. 转换 - `capitalize`: 将字符串的第一个字符转换为大写,其余字符转换为小写。 - `upcase`: 将整个字符串转换为大写。 - `downcase`:...
要避免这种情况,可以使用`clone`或`dup`方法创建副本: ```ruby h3 = h2 # 浅复制,改变h3会影响h2 h4 = h2.clone # 深复制,改变h4不会影响h2 ``` 至于Hash的排序,由于键和值可能为任意类型,排序并不直接。Ruby...
需要注意的是,如果只是想复制一个数组而不进行任何转换,应该使用`clone`或`dup`方法,而不是`collect`。`collect`更适用于对每个元素进行某种计算或转换,以生成一个新的、有变化的数组。 总结来说,Ruby中的迭代...
strict_arguments值结构需要使用确切数量的参数进行初始化:freeze自动冻结新实例:no_clone更改#clone以返回相同的对象默认情况下,只包含:dup_with_changes 。 没有 mixins,ValueStructs 几乎和普通结构一样快。 ...
7. 原型(Prototype)继承:虽然 Ruby 使用类来表示继承关系,但它的原型概念体现在 `Object#clone` 和 `Object#dup` 方法上,它们可以创建对象的副本。 8. 块(Blocks)和迭代器:Ruby 中的块是一段代码,可以用 `...