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

时间:2016-12-29 08:29:08

标签: ruby

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

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

这给出了如下输出:

Test this string
[Finished in 0.0s]

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

2 个答案:

答案 0 :(得分:49)

没有修改冻结的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.object_id ...行之前和之后检查a +=来验证这是您的案例中发生的事情。

答案 1 :(得分:3)

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

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

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

s1 << "testing again"

它会给出,RuntimeError:无法修改冻结的字符串

,但

冻结操作对象参考,而不是变量

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

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

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