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
<<
和+
表现不同的{{1}}差异。谁能告诉我这个的原因?
答案 0 :(得分:5)
他们正在完全他们应该做的事情。 <<
修改了调用它的字符串,而+
更接近str.dup << arg
。此行为是已定义的文档标准。
答案 1 :(得分:1)
@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
我们可以得出结论 - 是的,字符串“good”仍然被冻结。只有发生的事情是a
引用新对象“早上好”。只有a
的参考分配已更改。
答案 2 :(得分:0)
<<
和+
对所有字符串对象的行为不同,而不仅仅是冻结对象。一个(<<
)修改一个字符串,另一个(+
)返回一个新字符串而不修改原始字符串:
使用<<
:
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
专门用于禁止我在上面用<<
演示的行为(它可以防止对象被修改),因此在冻结的字符串上调用<<
会导致错误