2013-03-28 31 views
3

瀏覽Rails代碼庫我發現了許多對options.dup的引用。Ruby on Rails中options.dup的用途是什麼?

def to_xml(options = {}) 
    require 'builder' unless defined?(Builder) 
    options = options.dup 
    .... 
end 

顯然options.dup是重複選項散列,但爲什麼你希望在這種情況下做到這一點?

+1

在問這個問題之前,似乎沒有搜索已經完成。你應該總是試圖自己得到答案,如果你沒有找到答案,那麼你應該問stackoverflow。 – KULKING

+1

我搜索了,我沒有找到答案。這就是我在這裏問的原因 – Georgi

+2

這是一個明智的問題,由於作者使用英語作爲第二語言,這是一個不合理的問題。爲清晰起見進行編輯並投票決定。請儘量成爲一個更友善的人,我們是Rubyists。 – superluminary

回答

7

dup克隆一個對象。當你將一個對象傳遞給一個方法時,任何改變該對象內部狀態的東西都會反映到調用範圍中。例如,試試這個代碼:

def replace_two(options) 
    options[:two] = "hi there" 
end 

options = { one: "foo", two: "bar" } 
replace_two(options) 
puts options[:two] 

,將打印hi there,因爲replace_two()修改散列內容。

如果你想避免改變傳入options,你可以調用它.dup,然後克隆所做的任何更改將不會在呼叫範圍內得到體現:

def replace_two(options) 
    options = options.dup 
    options[:two] = "hi there" 
end 

options = { one: "foo", two: "bar" } 
replace_two(options) 
puts options[:two] 

將打印bar。這是在Principle of Least Astonishment之後的一種常見模式。在Ruby中,修改參數的方法通常以!後綴命名,以提醒用戶它們是破壞性/修改操作。該方法的非版本號應該被稱爲replace_two!以指示這種副作用。

+1

'dup'只是一個淺拷貝,正如@ denis-bu所述。它不會克隆嵌套的內部對象,只是第一級的內部對象。 –

+0

謝謝,非常好,詳細的解釋 – Georgi

5

dup創建對象的淺表副本。這是紅寶石核心的東西。由於在像哈希和數組等紅寶石對象通過引用傳遞,當您更改函數內的對象時,這將更改原始對象。如果這不是你想要的行爲 - 你創建一個副本...所以這段代碼的確如此。

ruby-doc

UPDATE

一兩件事。由於對象通過引用傳遞,因此options = options.dup將分配給options對新創建副本的變量引用。在to_xml內丟失了原始對象的引用。但它仍然可能引用了代碼,它調用to_xml

相關問題