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中如何复制对象 (deep clone)(转载)的更多相关文章

  1. CorelDRAW中六种复制对象的方法详解

    复制可保证对象的大小一致,复制也是所有操作中最基本的操作.CorelDRAW软件中支持多种复制对象的操作,本教程将详解CorelDRAW中六种复制对象的方法. 方法一 选择复制对象,点击编辑→复制,再 ...

  2. CorelDRAW中如何复制对象属性详解

    复制对象属性是一种比较特殊.重要的复制方法,它可以方便而快捷地将指定对象中的轮廓笔.轮廓色.填充和文本属性通过复制的方法应用到所选对象中.本教程将详解CorelDRAW中如何复制对象属性. Corel ...

  3. JavaScript 中的对象深度复制(Object Deep Clone)

    JavaScript中并没有直接提供对象复制(Object Clone)的方法. JavaScript中的赋值,其实并不是复制对象,而是类似`c/c++`中的引用(或指针),因此下面的代码中改变对象b ...

  4. 深入探讨JavaScript如何实现深度复制(deep clone)

    在代码复用模式里面有一种叫做“复制属性模式”(copying properties pattern).谈到代码复用的时候,很有可能想到的是代码的继承性(inheritance),但重要的是要记住其最终 ...

  5. ruby中的可调用对象--proc和lamdba

    ruby中将块转变成对象的三种方法 ruby中的大部分东西都是对象,但是块不是.那么,如果你想存下来一个块,方便以后使用,你就需要一个对象.ruby中有三种方法,把块转换成可以利用的对象. Proc. ...

  6. JavaScript 复制对象【Object.assign方法无法实现深复制】

    在JavaScript这门语言中,数据类型分为两大类:基本数据类型和复杂数据类型.基本数据类型包括Number.Boolean.String.Null.String.Symbol(ES6 新增),而复 ...

  7. ruby中symbol

    Symbol 是什么 Ruby 是一个强大的面向对象脚本语言(本文所用 Ruby 版本为1.8.6),在 Ruby 中 Symbol 表示“名字”,比如字符串的名字,标识符的名字. 创建一个 Symb ...

  8. ruby中的方法查找

    ruby中的方法调用都是 对象.方法 的形式,那么对象如何找到这个方法呢? 首先必须了解祖先链的概念,祖先链就是从一个类开始,到它的父类,再到父类的父类...一直到最终的起点(ruby中是BasicO ...

  9. ruby中的self

    self,自己,在ruby中表示当前对象或默认对象.程序执行的任一时刻,有且仅有一个self. 1.谁成为self,在什么位置成为self? 要知道哪个对象是self,就必须知道当前的上下文.上下文主 ...

随机推荐

  1. 海量数据挖掘MMDS week5: 计算广告Computational Advertising

    http://blog.csdn.net/pipisorry/article/details/49428053 海量数据挖掘Mining Massive Datasets(MMDs) -Jure Le ...

  2. 2015年iOS开发工程师前景分析

    "互联网+"概念的提出催生了大量互联网企业,越来越多的传统行业需要与互联网更深地渗透与融合.而在这股互联网化的浪潮中,行业却发现找不到优秀的互联网人才. 互联网企业数量持续增长,用 ...

  3. byte和长度为8的boolean数组互相转换

    由于byte是一个8位字节 所以可以用它来存放数组为8的boolean数组,这些在通信协议会经常用到.这里给出一个java代码对其互相转换的. package com.udpdemo.test2; i ...

  4. 小知识点BeanUtils.copyProperties

     通过BeanUtils.copyProperties可以时间拷贝对象中的值,下面的new String[]{"cid","agreeFlag"," ...

  5. android smartbar适配

    1.使用魅族的demo里的SmartBarUtils.java 2.在mainifest中的Application         android:theme="@android:style ...

  6. Android平台 Psensor传感器调试方法

    一. 驱动层调试1.在板级dts文件中增加相应的dts代码,如:调试sensor类,在代码中找到已经有的代码在修改,I2C使用那根(一般为I2C3),I2C地址(找datasheet或者FAE),哪个 ...

  7. JSP 对象的作用范围

    在JSP中,对象有四种范围:page.request.session和application page范围             所谓的page范围指单一的JSP页面范围,page范围内的对象只能在 ...

  8. 【一天一道LeetCode】#34. Search for a Range

    一天一道LeetCode系列 (一)题目 Given a sorted array of integers, find the starting and ending position of a gi ...

  9. C# BarCodeToHTML条码生成类

    来自:http://www.sufeinet.com/forum.php?mod=viewthread&tid=656&extra=page%3D1%26filter%3Dtypeid ...

  10. 【一天一道LeetCode】#4 Median of Two Sorted Arrays

    一天一道LeetCode (一)题目 There are two sorted arrays nums1 and nums2 of size m and n respectively. Find th ...