为什么没有赋值运算符允许我修改,没有编译器警告Ruby的常量?
-
21-08-2019 - |
题
在下面的两个例子我做同样的事情,创建一个常数字符串以及使用该方法的concat对其进行修改。因为它是一个常数,我期待一个编译器警告,但只收到第二个例子之一,当我使用赋值运算符。这是为什么?
X = "hello"
X.concat(" world")
puts X # no warning
X = "hello"
X = X.concat(" world")
puts X # warning: already initialized
由于CONCAT方法就地修改字符串,这通常我会做什么,因为没有必要使用分配新建分配FY操作。那么,为什么赋值运算符的存在会导致编译器,以确定这两个操作为不同?
解决方案
这是因为你重新定义一个新的十当你重新定义一个常量它给你的“已初始化”的错误。第一个例子并没有给这个错误,因为你不重新定义X,你正在修改它。
其他提示
在红宝石,变量基本上是指针到一个地方在包含对象的存储器 - 不是对象本身。在第二个例子中,要初始化常数X
指向第一行(X = "hello"
)的对象,并在第二行,你将再次初始化不断 - 但它已经指向一个对象,所以你得到的错误。
一个常量的永恒性并不意味着你不能改变的对象 - 它只是意味着你不能改变常量以指向的其他的对象
。如果你想使你的字符串“真正的”常数,尝试“冻结”:
X = "foo".freeze # => "foo"
X.concat("bar")
TypeError: can't modify frozen string
from (irb):2:in `concat'
from (irb):2
我真的建议您阅读 Ruby编程Languge 。
这是因为在恒定X
被存储到String
对象的引用。在你的第一个例子,你正在修改的String
对象的内部状态,而不是由恒存储的参考。在第二个示例中,将改变由恒定存储到其从String
方法返回的新concat
对象的引用。
镐头本书解释了这个这里。
不隶属于 StackOverflow