`

转帖 Ruby中复制对象的几种方法

    博客分类:
  • RUBY
阅读更多

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
http://www.artima.com/forums/flat.jsp?forum=123&thread=40913
好了, 复制这个小问题, 没想到也能引出这么长的文章来, 没想到吧?

转载请注明: 转自船长日志, 本文链接地址: http://www.cslog.cn/Content/ruby-deep-clone/
分享到:
评论

相关推荐

    轻松转帖之突破网页复制限制宣贯.pdf

    UBB转帖王是一种插件,它能够帮助用户快速去除复制下来的网页内容中的无用空格、文字干扰码、水印和空行等,优化复制内容,便于分享和阅读。 【其他浏览器解决方案】 除了火狐,其他浏览器如搜狗、遨游和世界之窗也...

    论坛转帖工具.rar

    标题中的“论坛转帖工具.rar”表明这是一个用于在论坛之间转移帖子的软件工具,通常用于帮助用户方便地将一个论坛的帖子内容复制到另一个论坛,可能是为了分享信息、讨论或保存重要的帖子。这类工具可能包括自动抓取...

    cad如何找到复制过来的图形.doc

    利用复制粘贴,不仅可以在 CAD 中将图形从一张图纸复制到另一张图纸,还可以粘贴到 WORD 或 EXCEL 里作为 OLE 对象,在 WORD 或 EXCEL 中双击图形就可以返回到 CAD 中进行修改,很多制造业单位都在 WORD 或 EXCEL 中...

    转帖经典---JAVA设计模式

    这些模式为程序员提供了一种标准化的方式,以便在面向对象编程中有效地组织和构建代码,提高代码的可读性、可维护性和复用性。在Java中,设计模式分为三类:创建型模式、结构型模式和行为型模式。 创建型模式关注于...

    贴吧转帖工具

    【贴吧转帖工具】是一种专为百度贴吧用户设计的便捷工具,主要用于提高用户在贴吧中的互动效率。通过这款工具,用户可以实现一键转帖和一键8经验签到的功能,极大地简化了传统操作流程,节省了用户的时间,提升了...

    UBB论坛转帖圣手.exe

    UBB论坛转帖圣手.exeUBB论坛转帖圣手.exe

    编辑人员转帖去水印工具

    总之,编辑人员转帖去水印工具如Teorex Inpaint,为图像编辑提供了便利,通过其独特的算法和技术,我们可以高效地去除图片中的水印,提高内容的质量。但在使用过程中,务必遵守版权法和相关法律法规,以维护良好的...

    转帖图片提取工具 v1.0.zip

    转帖图片提取工具可以对论坛...转帖图片提取工具使用方法: 将IP138上处理过的东西复制到上方的编辑框内,点击只要图片,下面的编辑框就出现结果,点击 复制结果 就可以把内容复制到剪切板中 转帖图片提取工具截图

    Html2UBBMaxcj_Softii论坛专用转帖工具

    HTML2UBBMaxcj 是一款专为Softii论坛设计的转帖工具,它主要用于将HTML格式的帖子内容转换成UBB代码,以便在论坛中更好地显示和分享。UBB(Universal BBCode)是一种轻量级的标记语言,常用于网络论坛,与HTML类似,...

    [转帖]世界编程大赛第一名写的程序

    标题和描述中的“世界编程大赛第一名写的程序”这一知识点,实际上指向了计算机科学与编程竞赛领域的一个重要概念:即在高水平的编程比赛中,优胜者所编写的代码往往蕴含着高级算法、数据结构以及编程技巧。...

    1分钟内抓到WPA握手包的方法!转帖的!!!

    WPA 握手包捕获方法 在WiFi网络安全测试中,捕获 WPA 握手包是一个非常重要的步骤。下面将详细介绍如何在 1 分钟内捕获 WPA 握手包的方法。 一、操作环境 在 Ubuntu 操作系统中,使用 aircrack-ng 工具包和 TP-...

    一键转帖功能插件 for 帝国CMS 6.0 GBK utf8 V1.0.rar

    本文将深入探讨“一键转帖功能插件”在帝国CMS 6.0系统中的应用与实现,该插件适用于GBK及UTF-8编码环境,旨在提升网站内容的分享与传播效率。我们将从安装步骤、工作原理、可能遇到的问题以及解决方案等方面进行...

    一键转帖功能插件 for 帝国CMS v1.0.rar

    总结一下,"一键转帖功能插件 for 帝国CMS v1.0" 提供了一种便捷的方式来增强帝国CMS站点的社交分享功能,通过简单的安装和配置,用户可以轻松地在多个平台上转发内容,有助于增加网站的曝光度和用户的参与度。...

    discuz X2转帖工具、采集工具

    3. 数据分析:通过批量发布和转帖,可以进行用户行为分析,了解哪种类型的内容更受论坛用户欢迎。 综上所述,“Discuz! X2转帖工具、采集工具”是提升Discuz! X2论坛运营效率的有效辅助手段,但使用时需谨慎,确保...

    转帖几个网站Banner的FLA源文件

    在这10个 Banner 的FLA源文件中,我们可以研究和学习以下几个关键知识点: 1. **矢量图形设计**:Banner通常使用矢量图形,因为它们可以在任何尺寸下保持清晰,不损失质量。通过分析FLA文件,我们可以学习如何使用...

    转帖工具ConvertX fordiscuz7.1/7.2 修改增强版.rar

    1.修改自Convert X转帖工具 2.新增批量替换关键词(原来是单个词语替换,可以利用这个功能删除一些网站的防转帖代码) 3.批量随机新增文字(新增内容可自定义,从而实现伪原创) 4.cookie记录替换和新增关键词(避免每次...

    转帖工具插件 for PHPwind 7.5 正式版.rar

    8. **故障排查**:如果在使用过程中遇到问题,如插件不工作、报错等,用户可以查阅插件提供的文档、社区论坛或联系开发者寻求帮助。 总的来说,"转帖工具插件 for PHPwind 7.5 正式版" 提供了一个高效且用户友好的...

    VxWorks 编程的几个误区(转帖)

    ### Vx Winds编程的几个误区解析 #### 一、引言 VxWorks 是一个实时操作系统(RTOS),广泛应用于嵌入式系统开发领域。对于初学者来说,在学习和使用过程中可能会遇到一些常见的误区和疑惑。本文旨在澄清这些误区,...

    遍历网页的一段Delphi代码(转帖)

    调用 `Get_All` 方法获取文档中的所有元素,并通过 `Get_Length` 方法获取这些元素的数量。 #### 2.4 遍历元素 ```delphi for tmpLoop := 0 to hlen - 1 do begin ``` 通过循环遍历所有元素,进一步处理每个元素。 ...

    新云4 一键复制更新今日插件

    新云4 一键复制更新今日插件花了半小时 搞了个一键转帖的最新软件下载。。 调用15个文件。 如果需要改个数 请修改 common/soft/newsoft.asp 里的maxperpage=15变量. 更改标题,请修改 common/soft/newsoft.asp 里...

Global site tag (gtag.js) - Google Analytics