ruby rails 的复制 dup clone

来源:互联网 发布:大麦盒子看电视软件 编辑:程序博客网 时间:2024/06/06 05:23
[ruby] view plaincopy
  1. Ruby内置的方法Object#clone和Object#dup可以用来copy一个对象,两者区别是dup只复制对象的内容,而clone还复制与对象相关联的内容,如singleton method  
  2. [ruby] view plaincopyprint?  
  3. s = "cat"    
  4. def s.upcase    
  5.     "CaT"    
  6. end    
  7. s_dup = s.dup    
  8. s_clone = s.clone    
  9. s_dup.upcase        #=> "CAT"  (singleton method not copied)    
  10. s_clone.upcase      #=> "CaT" (uses singleton method)    
  11.   
  12. dup和clone都是浅复制Shallow Copy,也就是只能复制接受方的内容,而如果接受方包含到其他对象的引用,那么就只是会复制这些引用了。  
  13. [ruby] view plaincopyprint?  
  14. arr1 = [ 1, "flipper", 3 ]    
  15. arr2 = arr1.dup    
  16. arr2[2] = 99    
  17. arr2[1][2] = 'a'    
  18. arr1                #=> [1, "flapper", 3]    
  19. arr2                #=> [1, "flapper", 99]    
  20. 可以看到arr1中有一个到String对象的引用,从而arr2也复制了这个引用,当arr2中修改这个引用时,arr1中的也会发生变化。  
  21. 如果要进行深复制Deep Copy,可以聪明的采用Marshal模块  
  22. [ruby] view plaincopyprint?  
  23. arr1 = [ 1, "flipper", 3 ]    
  24. arr2 = Marshal.load(Marshal.dump(arr1))    
  25. arr2[2] = 99    
  26. arr2[1][2] = 'a'    
  27. arr1                #=> [1, "flipper", 3]    
  28. arr2                #=> [1, "flapper", 99]    
  29. 现在就会发现arr2中对String对象的修改不会导致arr1的变化了,因为深了。。。不过Marshal模块并不能把所有的对象都序列化  
  30. class中还有一个与对象复制相关的特殊方法initialize_copy,这个方法会在信息复制完成后执行,看下面这个示例  
  31. [ruby] view plaincopyprint?  
  32. class Document    
  33.     attr_accessor :title:text    
  34.     attr_reader :timestamp    
  35.     
  36.     def initialize(title, text)    
  37.         @title@text = title, text    
  38.         @timestamp = Time.now    
  39.     end    
  40. end    
  41.     
  42. doc1 = Document.new("Random Stuff""Haha")    
  43. sleep 10    
  44. doc2 = doc1.clone    
  45.     
  46. doc1.timestamp == doc2.timestamp        #=> true    
  47. 也就是两个对象是完全一样的,构造函数initialize被跳过了,所以两个对象的时间戮timestamp是相同的。如果要采用执行复制操作时的时间,我们可以通过给Document类添加initialize_copy方法来实现。initialize_copy让程序员能完全控制对象复制的状态  
  48. [ruby] view plaincopyprint?  
  49. class Document    #Reopen the class    
  50.     def initialize_copy(other)    
  51.         @timestamp = Time.now    
  52.     end    
  53. end    
  54.     
  55. doc3 = Document.new("More Stuff""Haha")    
  56. sleep 10    
  57. doc4 = doc1.clone    
  58.     
  59. doc3.timestamp == doc4.timestamp        #=> false    
  60. 再次感慨Ruby的魅力。。。  
  61. PS:以上内容主要来自The Ruby Way  
  62.   
  63. 用Ruby复制一个对象(object)也许没有你想像的那么容易. 今天我google了半天, 做个总结吧.  
  64. 先从最简单的开始, b = a 是复制吗? 看代码说话:  
  65. >> a= [0,[1,2]]  
  66. >> b=a  
  67. >> b[0]=88  
  68. >> b[1][0]=99  
  69. >> b    
  70. => [88, [99, 2]]  
  71. >> a    
  72. => [88, [99, 2]]  
  73. 从上面代码发现, 一但修改b, 原来的a也同时被改变了. 甚至:  
  74.   
  75. >> b.equal?(a)  
  76. => true  
  77. 原来b跟a根本就是同一个object, 只是马甲不一样罢了. 所以b = a不是复制.  
  78. 那 b = a.dup呢?? 还是看代码:  
  79. >> a= [0,[1,2]]  
  80. >> b=a.dup  
  81. >> b[0]=88  
  82. >> b[1][0]=99  
  83. >> b  
  84. => [88, [99, 2]]  
  85. >> a  
  86. => [0, [99, 2]]  
  87. 情况似乎有所好转, 在修改b后, a还是有一部分被修改了.(0没有变,但原来的1变成了99).  
  88. 所以dup有时候是复制(如在Array只有一级时), 但有时不是复制哦.  
  89. 再来一个, b = a.clone呢? 上代码:  
  90. >> a= [0,[1,2]]  
  91. >> b=a.clone  
  92. >> b[0]=88  
  93. >> b[1][0]=99  
  94. >> b  
  95. => [88, [99, 2]]  
  96. >> a  
  97. => [0, [99, 2]]  
  98. 情况几乎跟dup一模一样. 所以clone也不一定可以相信哦!   
  99. 原来ruby中的dup和clone都是shallow复制, 只针对object的第一级属性.   
  100. 汗, 难道在Ruby中没有办法复制对像吗? 也不完全是, 看这个:  
  101. >> a= [0,[1,2]]  
  102. >> b=Marshal.load(Marshal.dump(a))  
  103. >> b[0]=88  
  104. >> b[1][0]=99  
  105. >> b  
  106. => [88, [99, 2]]  
  107. >> a= [0,[1,2]]  
  108. => [0, [1, 2]]  
  109. 修改b后a没有被改变!!! 似乎终于成功找到复制的办法了!!!  
  110. 为什么要加"似乎"呢? 因为有些object是不能被Marshal.dump的.如:  
  111. >> t=Object.new  
  112. >> def t.test; puts ‘test’ end  
  113. >> Marshal.dump(t)  
  114. TypeError: singleton can’t be dumped  
  115.     from (irb):59:in `dump’  
  116.     from (irb):59  
  117. 更完善的复制方案可以考虑给ruby增加一个deep clone功能, 可以参考以下链接:  
  118. http://d.hatena.ne.jp/pegacorn/20070417/1176817721  
  119. http://www.artima.com/forums/flat.jsp?forum=123&thread=40913 
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 助学贷款登录密码忘了怎么办 抖音换了手机登不了怎么办 微信忘记密码申诉失败怎么办 银行卡短信通知没了怎么办 斗鱼手机号被绑定了怎么办 网易邮箱不记得账号怎么办 qq号被盗申诉不回来怎么办 号被盗了申诉不回来怎么办 富士康离职后工资卡号没填怎么办? 填高考志愿时没填电话号码怎么办 铁路12306密码忘了怎么办 微销通提示网络请求失败怎么办 苹果手机出现不停播报情况怎么办 手做俯卧撑抬不起来怎么办 如果qq号被冻结了怎么办 买的qq号被冻结怎么办 联想平板怎么下载东西怎么办 所有浏览器都安装不了怎么办 忘记微博登录邮箱怎么办 丰巢验证码丢了怎么办 微博昵称忘了怎么办 163邮箱账号忘记了怎么办 苹果手机id邮箱忘记了怎么办 微信号没注销了怎么办 微信昵称换不了怎么办 微博支付密码忘记怎么办 微博支付密码忘记了怎么办 华为手机看不见截屏怎么办 支付宝密码错误被锁定怎么办 实名身份证的微信限额怎么办 工行网银登陆密码忘了怎么办 美亚买的东西坏了怎么办 海带宝转运到香港怎么办 海带宝转运仓库入库错误怎么办 三星s7edge密码忘了怎么办 ie网页被拦截了怎么办 手机打开百度网页弹出广告怎么办 网站策略服务已被禁用怎么办 谷歌浏览器打不开网页怎么办 mac用户名密码忘记了怎么办 苹果7网速太慢怎么办