2016-12-29 49 views
15

我正在使用紅寶石凍結方法。就凍結的定義而言,它凍結了被調用的對象的值。後面我們不能修改那個對象的值。我一定要實現相同的任務,我有一個對象,我執行下面的代碼+ =運算符似乎修改了凍結字符串

a = "Test" 
a.freeze 
a += "this string" 
puts a 

這使輸出如下:

Test this string 
[Finished in 0.0s] 

爲什麼它被修改我的冷凍字符串?

+3

[凍結在Ruby中的變量不工作]的可能的複製(http://stackoverflow.com/questions/17067171/freezing-variables-in-ruby-不工作) – Manishh

+2

變量有所不同;這就是爲什麼他們被稱爲變量。 –

+1

我看到這是重複的,但這是一個很好的答案,這讓我不願意在它上面使用dup錘。我寧願將[提名的示例](http://stackoverflow.com/questions/17067171/freezing-variables-in-ruby-doesnt-work)標記爲此問題的副本,儘管它比較老 - 它是不是沒有那麼幹淨。 –

回答

46

沒有被修改的冷凍String

a += "this string" 

這是在內部紅寶石一樣

a = a + "this string" 

當您添加您要重新分配a到一個新的String在Ruby中有兩個String對象,它將創建一個包含結果的新String(這是的正常行爲運算符支持它的大多數對象)。這使原來的「測試」和「這個字符串」值保持不變。原始的凍結字符串(包含「測試」)將保留在內存中,直到它被垃圾收集爲止。它可以被收集,因爲你已經失去了對它的所有引用。

如果你試圖修改該對象在這種地方:

a << "this string" 

,那麼你應該會看到一個錯誤信息RuntimeError: can't modify frozen String

基本上,你搞糊塗a,局部變量,與String對象它正指向它。局部變量可以隨時重新分配,與Ruby存儲的對象無關。您可以通過在您的a += ...行前後檢查a.object_id來驗證您的情況發生了什麼。

+4

另外值得注意的是:'a.object_id'前後是完全不同的。這是一個有用的診斷,當東西表現*奇怪*,就像一個有克隆元素的數組。 – tadman

2

冷凍方法防止你改變對象,它變成一個目的爲恆定

s1 = "its testing" 
s1.freeze 
puts "Object ID ===", s1.obejct_id 

因此,凍結對象後,嘗試修改它會導致TypeError。

s1 << "testing again" 

它會給,RuntimeError:不能修改冷凍字符串

BUT,

凍結一個對象引用操作,而不是在一個可變

s1 += "New Testing" 
puts "Object ID ===", s1.obejct_id 

將指向評估一個新對象並檢查其對象ID。

有關詳細信息,請參閱本網站, http://rubylearning.com/satishtalim/mutable_and_immutable_objects.html