+ =运算符似乎修改冻结的字符串

我正在使用ruby冻结法。 就冻结的定义而言,它会冻结调用它的对象的值。 我们无法在其后修改该对象的值。 我必须完成相同的任务,我有一个对象,我正在执行以下代码

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

这给出了如下输出:

 Test this string [Finished in 0.0s] 

为什么要修改冻结的字符串?

什么都没有修改你的冷冻String

您正在将a重新分配给新的String

 a += "this string" 

这与Ruby内部相同

 a = a + "this string" 

在Ruby中添加两个String对象时,它将创建一个包含结果的新String(这是支持它的大多数对象上+运算符的正常行为)。 这使得原始的“Test”和“this string”值保持不变。 原始的冻结字符串(包含“测试”)将保留在内存中,直到它被垃圾收集。 可以收集它,因为您丢失了对它的所有引用。

如果您尝试像这样修改对象:

 a << "this string" 

那么你应该看到一条错误消息RuntimeError: can't modify frozen String

基本上,您已将局部变量a与它所指向的String对象混淆。 可以随时重新分配局部变量,而与Ruby存储的对象无关。 您可以通过在a += ...行之前和之后检查a.object_id来validation这是您的情况。

冻结方法阻止您更改对象,它将对象转换为常量

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

因此,在冻结对象后,尝试修改它会导致TypeError。

 s1 << "testing again" 

它会给出,RuntimeError:无法修改冻结的String

但,

冻结操作对象引用 ,而不是变量

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

将指向评估到新对象并检查其对象ID。

有关详细信息,请参阅此站点http://rubylearning.com/satishtalim/mutable_and_immutable_objects.html