在下面的两个例子我做同样的事情,创建一个常数字符串以及使用该方法的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对象的引用。

镐头本书解释了这个这里

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top