Ruby中复制对象的几种方法

Ruby内置的方法Object#clone和Object#dup可以用来copy一个对象,两者区别是dup只复制对象的内容,而clone还复制与对象相关联的内容,如singleton method

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,也就是只能复制接受方的内容,而如果接受方包含到其他对象的引用,那么就只是会复制这些引用了。

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模块

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,这个方法会在信息复制完成后执行,看下面这个示例

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让程序员能完全控制对象复制的状态

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

TAGS:Ruby

10 COMMENTS >>LEAVE<<

  1. kangzj

    嗯嗯,先把事情忙完,一定搞搞Ruby

  2. happybabe

    还没看ruby,不懂.看到一个有趣的东东-tiddlywiki

  3. ABitNo
    @happybabe

    TiddlyWiki是个非常小巧酷炫的wiki引擎,全部程序只是一个一百多K的HTML页面。TiddlyWiki用CSS+HTML+javascript写成,可以在多种浏览器上浏览。。。

    只有个html能做什么啊。。。

  4. happybabe
    @ABitNo

    可以当记事本,可以当本地wiki,直接上传到免费空间就是个站点.不分后台前端,不用数据库,可随身携带,有一定量插件和主题.我想把它当本地wiki用,windows,linux通用,看效果怎么样.本来想用mediawiki,不过需要php环境,备份数据库很麻烦.

  5. ABitNo
    @happybabe

    你起床也真早。。。
    万物階有存在的理由。。。

    不过用mediawiki还真不错,数据库备份不麻烦的,都很简单。。。

  6. happybabe
    @ABitNo

    夜猫子也起早了?Arch wiki也是Powered by mediawiki.Arch wiki实在是太好,没有它估计我现在都无法入门linux.Ubuntu wiki看完一头雾水,茫然无措. 

  7. 数数

    好复杂的东西。编程= = 我从来记不住代码。连VB的几乎都忘了。。

  8. ABitNo
    @happybabe

    这今天起早去爬山了,爬了一天,累死了,而且还下了大雨。。。

  9. ABitNo
    @数数

    yi哈哈。。。个人爱好而已。。。
    我就是喜欢这些东西,除了这也没什么会的了。。。

  10. happybabe

    没电脑,好闷好寂寞.用手机上来打个招呼,睡觉喽~

LEAVE A RESPONSE >>CANCEL<<

loader