为什么"<<"和"+"对冻结字符串对象的行为不同?


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 专门设计用于禁止我上面用 << 演示的那种行为(它可以防止对象被修改(,因此对冻结字符串调用 << 会导致错误。

相关内容

最新更新