我正在经历The Well Grounded Rubyist,并对以下示例感到困惑。
假设我们有一个字符串数组:
numbers = ["one", "two", "three"]
如果我冻结此阵列,我无法执行以下操作:
numbers[2] = "four"
该语句是运行时错误,但是:
numbers[2].replace("four")
不是。
本书解释说,在最后两个语句的第一个中,我们正在尝试访问该数组。这就是我发现令人困惑的原因,因为我认为我们正在尝试访问数组的第三个元素,这是一个字符串对象。那与上一个陈述有何不同?
答案 0 :(得分:5)
这是不同的,因为在声明中,你正在调用String#replace
。正如您所料,对Array#replace
的调用将失败。
numbers.replace [1,2,3]
TypeError: can't modify frozen array
任何给定数组索引处的对象引用可能是任意复杂的,并且冻结数组的作用不是保持这些对象不被改变......它只是想保持数组不变。你可以看到这个:
ree-1.8.7> numbers[2].object_id
=> 2149301040
ree-1.8.7> numbers[2].replace "four"
=> "four"
ree-1.8.7> numbers[2].object_id
=> 2149301040
在numbers[2]
运行后, object_id
具有相同的String#replace
;数组实际上没有改变。
答案 1 :(得分:0)
数组是object_id的列表。 String#replace是特殊的 - 它会更改字符串,但会保留object_id。因此,object_id的列表不会更改,并且Array不会检测到任何更改。
您可以冻结数组的每个字符串。然后,String#replace将导致错误。