2012-02-03 120 views
0

此行爲是否正確?我跑了一些類似於下面的代碼:哈希合併行爲

@a_hash = {:a => 1} 
x = @a_hash 
x.merge!({:b => 2}) 

在所有的結束,X的值已經改變預期,但如此有@a_hash值。我將{:a => 1,:b => 2}作爲它們的值。這是Ruby中的正常行爲嗎?

回答

4

是,實例變量@a_hash和局部變量x商店參考到相同Hash實例,並當改變此實例(使用增變方法merge!到位改變對象),這些變量將被評估爲相同的值。

您可能需要使用merge方法創建對象的副本,不改變原來的一個:

@a_hash = {:a => 1} 
x = @a_hash 
y = x.merge({:b => 2}) 
# y => {:a => 1, :b => 2} 
# x and @a_hash => {:a => 1} 
+0

啊,好的。我懷疑那是發生了什麼事。謝謝。 – blim8183 2012-02-03 19:49:45

2

@a_hash鏈接爲x。所以,如果你想@a_hash沒有改變,你應該這樣做:

@a_hash = {:a => 1} 
x = @a_hash.clone 
x.merge!({:b => 2}) 
+2

當我完全等價於'x = @ a_hash.merge(:b => 2)時,我不推薦克隆' – tokland 2012-02-03 20:22:25

1

是的,這是紅寶石(和大多數其他語言)的正常行爲。 x@a_hash都是對同一個對象的引用。通過調用merge!您更改該對象,並通過引用它的所有變量更改可見。

如果您不想要這種行爲,您應該不使用變異方法(即使用x = x.merge(...))或在變異之前複製對象(即x = @a_hash.dup)。