2012-12-31 158 views
4

我正在尋找一些技術來深入複製Ruby(MRI 1.9.3)中的對象。
我遇到了下面的例子,但我不確定#dup方法的實現。 我測試了它,它確實有效,但我不明白這個方法的邏輯步驟,因此我不會在我自己的代碼中使用它。Ruby:對象深度複製

是否聲明@name = @name.dup指的是iVar 裏面的的副本?怎麼樣?我看不到它。

任何人都可以解釋它嗎?
另外,有沒有更好的方法?

class MyClass 
    attr_accessor :name 

    def initialize(arg_str) # called on MyClass.new("string") 
    @name = arg_str   # initialize an instance variable 
    end 

    def dup 
    the_copy = super  # shallow copy calling Object.dup 
    @name = @name.dup  # new copy of istance variable 
    return the_copy   # return the copied object 
    end 
end 
+0

相關:http://stackoverflow.com/questions/8206523/how-to-create-a-deep-copy-of-an-object-in-ruby –

回答

6

這是一個非常薄,非常具體的「深層複製」實現。它演示的是在克隆中創建一個獨立的@name實例變量,以便通過就地操作修改其名稱並不會產生更改克隆的副作用。

通常,深度複製操作對嵌套數組或哈希等事物很重要,但它們也適用於任何具有指向該類事物的屬性的對象。

在你的情況下,爲了使對象具有更強大的dup方法,你應該對每個有問題的屬性調用dup,但我認爲這個例子有點失敗。它所做的是用原件替換原件中的@name,這可能會破壞您的任何參考。

一個更好的版本是:

def dup 
    copy = super 
    copy.make_independent! 
    copy 
end 

def make_independent! 
    instance_variables.each do |var| 
    value = instance_variable_get(var) 

    if (value.respond_to?(:dup)) 
     instance_variable_set(var, value.dup) 
    end 
    end 
end 

這應該有重複其支持dup方法的任何實例變量的影響。這會跳過數字,布爾值和nil這些不能重複的內容。

0

當你做super時,實例方法@name將在原始和重複之間共享。通過做@name = @name.dup,原始字符串得到一個新的字符串實例@name,結果與複製實例具有不同的@name