破坏性字符串赋值
Destructive string assignment
在此代码中,
def string_assignment_original_name(name)
save_name = name
name.upcase!
name
end
如果 name = "Bob"
,输出将为 "BOB"
。同时在此代码中,
def string_assignment_save_name(name)
save_name = name
name.upcase!
save_name
end
如果name = "Bob"
,输出也是"BOB"
.
为什么会这样?
Ruby 变量基本上是 "object references" ,这是一种内部指针。 name
和 save_name
在就地修改之前和之后都引用同一个对象。
查看 name.object_id
和 save_name.object_id
的结果,了解结果如何,因为该方法是 window 内部发生的事情:
name = "bob"
name.object_id
# => ...2980
save_name = name
save_name.object_id
# => ...2980
name.upcase!
name.object_id
# => ...2980
现在,如果您通过 .dup
或 .clone
之类的方法复制对象,或者如果您通过其他过程创建一个全新的字符串,那么它就是一个新对象:
name = name.downcase
name.object_id
# => ...8480
现在你有两个对象在玩:
name.object_id
# => ...8480
save_name.object_id
# => ...2980
这些 object_id
值对于所有意图都是随机的,但每个对象实例都是唯一的。如果两个对象具有相同的 object_id
值,则它们是同一个对象。†
† 从技术上讲,对象可以将其 object_id
方法覆盖为 return 其他方法,但这种情况很少见。
在此代码中,
def string_assignment_original_name(name)
save_name = name
name.upcase!
name
end
如果 name = "Bob"
,输出将为 "BOB"
。同时在此代码中,
def string_assignment_save_name(name)
save_name = name
name.upcase!
save_name
end
如果name = "Bob"
,输出也是"BOB"
.
为什么会这样?
Ruby 变量基本上是 "object references" ,这是一种内部指针。 name
和 save_name
在就地修改之前和之后都引用同一个对象。
查看 name.object_id
和 save_name.object_id
的结果,了解结果如何,因为该方法是 window 内部发生的事情:
name = "bob"
name.object_id
# => ...2980
save_name = name
save_name.object_id
# => ...2980
name.upcase!
name.object_id
# => ...2980
现在,如果您通过 .dup
或 .clone
之类的方法复制对象,或者如果您通过其他过程创建一个全新的字符串,那么它就是一个新对象:
name = name.downcase
name.object_id
# => ...8480
现在你有两个对象在玩:
name.object_id
# => ...8480
save_name.object_id
# => ...2980
这些 object_id
值对于所有意图都是随机的,但每个对象实例都是唯一的。如果两个对象具有相同的 object_id
值,则它们是同一个对象。†
† 从技术上讲,对象可以将其 object_id
方法覆盖为 return 其他方法,但这种情况很少见。