1
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<<并且+不会像他们应该的那样表现。谁能告诉我这是什么原因?

4

3 回答 3

5

他们正在做他们应该做的事情。<< 修改调用它的字符串,而+更接近str.dup << arg. 此行为是已定义的、记录在案的标准。

于 2013-02-16T18:16:51.747 回答
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已更改。

于 2013-02-16T19:23:24.237 回答
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专门设计用于禁止我在上面演示的那种行为<<(它防止对象被修改),因此调用<<冻结的字符串会导致错误。

于 2014-06-06T19:13:06.203 回答