irb(main):009:0> a = "good"
=> "good"
irb(main):010:0> a = "good" + "morning"
=> "goodmorning"
irb(main):011:0> a = "good"
=> "good"
irb(main):012:0> a << " morning"
=> "good morning"
到目前为止,concatenation
操作员都工作正常。
irb(main):013:0> a = "good"
=> "good"
irb(main):014:0> a.freeze
=> "good"
irb(main):015:0> a.frozen?
=> true
irb(main):016:0> a << " welcome"
RuntimeError: can't modify frozen String
from (irb):16
from /usr/bin/irb:12:in `<main>'
irb(main):017:0> a = a + " welcome"
=> "good welcome"
但是,对于frozen
字符串,从<<
和+
没有按照应有的方式表现IRB
可以清楚地看到差异。谁能告诉我这其中的原因?
他们正在做他们应该做的事情。 <<
修改调用它的字符串,而+
更接近str.dup << arg
。此行为是定义的、记录在案的标准。
@Linuxios答案是完美的。
但仍然在这里,我试图以更透明的方式展示这种修改:
@ubuntu:~$ irb --simple-prompt
>> a = "good"
=> "good"
>> a.freeze
=> "good"
>> a.frozen?
=> true
>> a.object_id
=> 10557720 # holds the reference to the "good" string object.
>> a = a + " morning"
=> "good morning"
>> a.object_id
=> 10415700 # holds the reference to the new string object "good morning".
>> a.frozen?
=> false
>> ObjectSpace._id2ref(10415700)
=> "good morning"
>> ObjectSpace._id2ref(10557720)
=> "good"
>> ObjectSpace._id2ref(10557720).frozen?
=> true
我们可以得出结论 - 是的,字符串"好"仍然被冻结。只有发生的事情是a
引用新对象"早上好"。仅更改了对a
的引用分配。
<<
和+
在所有字符串对象上的行为不同,而不仅仅是冻结的对象。一个(<<
(修改一个字符串,另一个(+
(返回一个新字符串而不修改原始字符串:
<<
:
string1 = "good"
#=> "good"
string2 = string1
#=> "good"
string1 << " morning"
#=> "good morning"
string1
#=> "good morning"
string2
#=> "good morning"
+
:
string1 = "good"
#=> "good"
string2 = string1
#=> "good"
string1 = string1 + " morning"
#=> "good morning"
string1
#=> "good morning"
string2
#=> "good"
Object#freeze
专门设计用于禁止我上面用 <<
演示的那种行为(它可以防止对象被修改(,因此对冻结字符串调用 <<
会导致错误。