瀏覽Rails代碼庫我發現了許多對options.dup的引用。Ruby on Rails中options.dup的用途是什麼?
def to_xml(options = {})
require 'builder' unless defined?(Builder)
options = options.dup
....
end
顯然options.dup是重複選項散列,但爲什麼你希望在這種情況下做到這一點?
瀏覽Rails代碼庫我發現了許多對options.dup的引用。Ruby on Rails中options.dup的用途是什麼?
def to_xml(options = {})
require 'builder' unless defined?(Builder)
options = options.dup
....
end
顯然options.dup是重複選項散列,但爲什麼你希望在這種情況下做到這一點?
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!
以指示這種副作用。
'dup'只是一個淺拷貝,正如@ denis-bu所述。它不會克隆嵌套的內部對象,只是第一級的內部對象。 –
謝謝,非常好,詳細的解釋 – Georgi
dup
創建對象的淺表副本。這是紅寶石核心的東西。由於在像哈希和數組等紅寶石對象通過引用傳遞,當您更改函數內的對象時,這將更改原始對象。如果這不是你想要的行爲 - 你創建一個副本...所以這段代碼的確如此。
UPDATE
一兩件事。由於對象通過引用傳遞,因此options = options.dup
將分配給options
對新創建副本的變量引用。在to_xml
內丟失了原始對象的引用。但它仍然可能引用了代碼,它調用to_xml
在問這個問題之前,似乎沒有搜索已經完成。你應該總是試圖自己得到答案,如果你沒有找到答案,那麼你應該問stackoverflow。 – KULKING
我搜索了,我沒有找到答案。這就是我在這裏問的原因 – Georgi
這是一個明智的問題,由於作者使用英語作爲第二語言,這是一個不合理的問題。爲清晰起見進行編輯並投票決定。請儘量成爲一個更友善的人,我們是Rubyists。 – superluminary