Ruby内置的方法Object#clone和Object#dup可以用来copy一个对象,两者区别是dup只复制对象的内容,而clone还复制与对象相关联的内容,如singleton method
[ruby] view plaincopyprint?
s = "cat"
def s.upcase
"CaT"
end
s_dup = s.dup
s_clone = s.clone
s_dup.upcase #=> "CAT" (singleton method not copied)
s_clone.upcase #=> "CaT" (uses singleton method)

dup和clone都是浅复制Shallow Copy,也就是只能复制接受方的内容,而如果接受方包含到其他对象的引用,那么就只是会复制这些引用了。
[ruby] view plaincopyprint?
arr1 = [ 1, "flipper", 3 ]
arr2 = arr1.dup
arr2[2] = 99
arr2[1][2] = 'a'
arr1 #=> [1, "flapper", 3]
arr2 #=> [1, "flapper", 99]
可以看到arr1中有一个到String对象的引用,从而arr2也复制了这个引用,当arr2中修改这个引用时,arr1中的也会发生变化。
如果要进行深复制Deep Copy,可以聪明的采用Marshal模块
[ruby] view plaincopyprint?
arr1 = [ 1, "flipper", 3 ]
arr2 = Marshal.load(Marshal.dump(arr1))
arr2[2] = 99
arr2[1][2] = 'a'
arr1 #=> [1, "flipper", 3]
arr2 #=> [1, "flapper", 99]
现在就会发现arr2中对String对象的修改不会导致arr1的变化了,因为深了。。。不过Marshal模块并不能把所有的对象都序列化
在class中还有一个与对象复制相关的特殊方法initialize_copy,这个方法会在信息复制完成后执行,看下面这个示例
[ruby] view plaincopyprint?
class Document
attr_accessor :title, :text
attr_reader :timestamp

def initialize(title, text)
@title, @text = title, text
@timestamp = Time.now
end
end

doc1 = Document.new("Random Stuff", "Haha")
sleep 10
doc2 = doc1.clone

doc1.timestamp == doc2.timestamp #=> true
也就是两个对象是完全一样的,构造函数initialize被跳过了,所以两个对象的时间戮timestamp是相同的。如果要采用执行复制操作时的时间,我们可以通过给Document类添加initialize_copy方法来实现。initialize_copy让程序员能完全控制对象复制的状态
[ruby] view plaincopyprint?
class Document #Reopen the class
def initialize_copy(other)
@timestamp = Time.now
end
end

doc3 = Document.new("More Stuff", "Haha")
sleep 10
doc4 = doc1.clone

doc3.timestamp == doc4.timestamp #=> false
再次感慨Ruby的魅力。。。
PS:以上内容主要来自The Ruby Way

用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

转载于:https://www.cnblogs.com/qinyan20/p/9674004.html

ruby中的复制 dup clone相关推荐

  1. Ruby中的设计模式

    继续 上 节讲述过的Singleton . Proxy 及 Iterator各模式,本节再来考察几个别的设计模式.下面按顺序来考察 Prototype . Template Method 和 Obse ...

  2. torch中的copy()和clone()

    torch中的copy()和clone() 1.torch中的copy()和clone() y = torch.Tensor(2,2):copy(x) --- 1 修改y并不改变原来的x y = x: ...

  3. JAVA中浅复制与深复制

    來源:http://coolmist.javaeye.com/blog/127455 1.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引 ...

  4. 【转】C#中数组复制的4种方法

    C#中数组复制的4种方法 from:http://blog.csdn.net/burningcpu/article/details/1434167 今天旁边的同事MM叫我调了一段程序,她想复制一个数组 ...

  5. oracle10g数据库复制,oracle -10g 中Duplicate 复制数据库

    oracle --10g 中Duplicate 复制数据库 本次实验通过duplicate命令,在本机环境中创建一个复制数据库.目标数据库为hongye.复制数据库为catdb. 环境别名设置: al ...

  6. 如何优雅的在ubuntu终端中使用复制粘贴

    如何优雅的在ubuntu终端中使用复制粘贴 文章目录 前言 更改终端里面的复制粘贴命令 修改鼠标按键映射 介绍 安装 依赖 编译安装 配置文件 前言 安装了ubuntu20.4 后发现终端里面的复制粘 ...

  7. 复制对象clone(深复制和浅复制)

    Java中对象的创建 clone顾名思义就是复制, 在Java语言中, clone方法被对象调用,所以会复制对象.所谓的复制对象,首先要分配一个和源对象同样大小的空间,在这个空间中创建一个新的对象.那 ...

  8. Ruby中的设计模式——《松本行弘的程序世界》

    < 设计模式 > 一书是用C++ 和 Smalltalk 介绍模式实例的.看了那些例子,大家都会感觉到,绝大多数的模式用 Smalltalk 实现起来非常简单.这是为什么呢? 因为Smal ...

  9. Ruby中爬虫的实现

    2019独角兽企业重金招聘Python工程师标准>>> Ruby中实现网页抓取,一般用的是mechanize,使用非常简单. 安装 sudo gem install mechaniz ...

最新文章

  1. python从入门到精通怎么样-Python 从入门到精通:一个月就够了
  2. sequelize 连接2个数据库_数据库激荡 40 年,NoSQL、NewSQL谁能接棒?
  3. 分布式任务调度平台一站式讲解
  4. BDKRHash详解
  5. python 魔法函数是什么意思_Python 中的魔法函数
  6. Linux bind DNS配置
  7. format函数_Python学习教程:Python3之字符串格式化format函数详解(上)
  8. linux7.3的域名配置表,Centos7.3 安装部署Nginx并配置https的方法步骤
  9. C# 23种设计模式
  10. 形式语义学关于带权有向图最短路径的有模式函数算法
  11. Java代码页面显示报表_Web报表开发中使用快逸报表分页标签:显示第几页和共几页...
  12. android led 字体下载,Android app全局字体设置
  13. Java 运行环境安装(JRE JDK 区别)
  14. Mac中隐藏/显示文件或文件夹
  15. Flutter从相册选择图片和相机拍照(image_picker)
  16. matlab拟合公式不准确,Matlab拟合函数误差:函数值和YDATA大小不相等
  17. 【C#进阶二】C#中的正则表达式知识总结(字符转义/字符类/ 定位点/ 分组构造 /数量词/反向引用构造/替换构造/替代/正则表达式选项)(理论篇)
  18. suse linux乱码,轻松解决Suse中文乱码问题
  19. Win7x64系统过TP的一些尝试和目前遇到的问题
  20. Qt UI界面美化教程1:【“飞扬青云” Qt精美控件】使用教程1

热门文章

  1. ASCII码对照表 转帖
  2. HTML-通知公告Tips
  3. 四则运算关于加括号的思路
  4. set built-in function
  5. python for selenium 数据驱动测试
  6. IOS学习之UINavigationController详解与使用(一)添加UIBarButtonItem
  7. Install marvel and head plugin for ealsticsearch
  8. Spring+SpringMvc+Mybatis框架集成搭建教程二(依赖配置及框架整合)
  9. WCF 之 消息契约(MessageContract)
  10. Bash shell的内建命令:type