为什么缺少赋值运算符允许我修改 Ruby 常量而不会出现编译器警告?
在下面的两个示例中,我做了同样的事情,创建一个常量 String 并使用 concat 方法来修改它。 因为它是一个常量,所以我预计会出现编译器警告,但当我使用赋值运算符时,仅在第二个示例中收到一个警告。 为什么是这样?
X = "hello"
X.concat(" world")
puts X # no warning
X = "hello"
X = X.concat(" world")
puts X # warning: already initialized
由于 concat 方法会就地修改字符串,因此我通常会这样做,因为不需要使用赋值运算符。 那么,为什么赋值运算符的存在会导致编译器将这两个操作识别为不同的呢?
In the following two examples I do the same thing, creating a constant String and using the concat method to modify it. Because it's a constant, I expect a compiler warning but only receive one in the second example when I use the assignment operator. Why is this?
X = "hello"
X.concat(" world")
puts X # no warning
X = "hello"
X = X.concat(" world")
puts X # warning: already initialized
Since the concat method modifies the string in place, that's normally what I would do, since there's no need to use an assigment operator. So, why does the presence of the assignment operator cause the compiler to identify these two operations as being different?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
在 Ruby 中,变量本质上是指向内存中包含对象的位置的指针,而不是对象本身。 在第二个示例中,您将初始化常量
X
以指向第一行中的对象 (X = "hello"
),在第二行中,您是再次初始化常量——但它已经指向一个对象,所以你会得到错误。常量的不变性并不意味着您不能更改该对象 - 它只是意味着您不能更改该常量以指向另一个对象。
In Ruby, variables are essentially pointers to a place in a memory containing an object -- not the object itself. In the second example, you are initializing a constant
X
to point to an object in the first line (X = "hello"
), and in the second line, you are again initializing the constant -- but it already points to an object, so you get the error.A constant's immutability doesn't mean you can't alter the object -- it just means you can't change the constant to point to another object.
这是因为您正在重新定义一个新的 X。当您重新定义常量时,它会给出“已初始化”错误。 第一个示例不会给出此错误,因为您没有重新定义 X,而是在修改它。
This is because you're re-defining a new X. When you redefine a constant it gives you the "already initialized" error. The first example does not give this error because you're not redefining X, you're modifying it.
如果您想让字符串“真实”不变,请尝试“冻结”:
我真的鼓励您阅读 Ruby 编程语言。
If you want to make your string "real" constant, try 'freeze':
I really encourage you to read The Ruby Programming Languge.
这是因为常量
X
存储了对String
对象的引用。 在第一个示例中,您正在修改 String 对象的内部状态,而不是常量存储的引用。 在第二个示例中,您将常量存储的引用更改为从concat
方法返回的新String
对象。PickAxe 书在此处对此进行了解释。
This is because the constant
X
is storing a reference to aString
object. In your first example, you are modifying the internal state of theString
object, but not the reference stored by the constant. In the second example, you are changing the reference stored by the constant to a newString
object which is returned from theconcat
method.The PickAxe book explains this here.