Ruby中复制对象的几种方法

来源:互联网 发布:淘宝助理批量下架宝贝 编辑:程序博客网 时间:2024/05/29 19:10

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

s = "cat"def s.upcase"CaT"ends_dup = s.dups_clone = s.clones_dup.upcase#=> "CAT"  (singleton method not copied)s_clone.upcase#=> "CaT" (uses singleton method)

dup和clone都是浅复制Shallow Copy,也就是只能复制接受方的内容,而如果接受方包含到其他对象的引用,那么就只是会复制这些引用了。

arr1 = [ 1, "flipper", 3 ]arr2 = arr1.duparr2[2] = 99arr2[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] = 99arr2[1][2] = 'a'arr1#=> [1, "flipper", 3]arr2#=> [1, "flapper", 99]

现在就会发现arr2中对String对象的修改不会导致arr1的变化了,因为深了。。。不过Marshal模块并不能把所有的对象都序列化

在class中还有一个与对象复制相关的特殊方法initialize_copy,这个方法会在信息复制完成后执行,看下面这个示例

class Documentattr_accessor :title, :textattr_reader :timestampdef initialize(title, text)@title, @text = title, text@timestamp = Time.nowendenddoc1 = Document.new("Random Stuff", "Haha")sleep 10doc2 = doc1.clonedoc1.timestamp == doc2.timestamp#=> true
也就是两个对象是完全一样的,构造函数initialize被跳过了,所以两个对象的时间戮timestamp是相同的。如果要采用执行复制操作时的时间,我们可以通过给Document类添加initialize_copy方法来实现。initialize_copy让程序员能完全控制对象复制的状态

class Document    #Reopen the classdef initialize_copy(other)@timestamp = Time.nowendenddoc3 = Document.new("More Stuff", "Haha")sleep 10doc4 = doc1.clonedoc3.timestamp == doc4.timestamp#=> false
再次感慨Ruby的魅力。。。
PS:以上内容主要来自The Ruby Way


原创粉丝点击