为什么缺少赋值运算符允许我修改 Ruby 常量而不会出现编译器警告?

发布于 2024-07-15 18:04:50 字数 364 浏览 2 评论 0原文

在下面的两个示例中,我做了同样的事情,创建一个常量 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

丘比特射中我 2024-07-22 18:04:50

在 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.

↙温凉少女 2024-07-22 18:04:50

这是因为您正在重新定义一个新的 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.

北座城市 2024-07-22 18:04:50

如果您想让字符串“真实”不变,请尝试“冻结”:

X = "foo".freeze        # => "foo" 
X.concat("bar")

TypeError: can't modify frozen string
    from (irb):2:in `concat'
    from (irb):2

我真的鼓励您阅读 Ruby 编程语言

If you want to make your string "real" constant, try 'freeze':

X = "foo".freeze        # => "foo" 
X.concat("bar")

TypeError: can't modify frozen string
    from (irb):2:in `concat'
    from (irb):2

I really encourage you to read The Ruby Programming Languge.

我们的影子 2024-07-22 18:04:50

这是因为常量 X 存储了对 String 对象的引用。 在第一个示例中,您正在修改 String 对象的内部状态,而不是常量存储的引用。 在第二个示例中,您将常量存储的引用更改为从 concat 方法返回的新 String 对象。

PickAxe 书在此处对此进行了解释。

This is because the constant X is storing a reference to a String object. In your first example, you are modifying the internal state of the String object, but not the reference stored by the constant. In the second example, you are changing the reference stored by the constant to a new String object which is returned from the concat method.

The PickAxe book explains this here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文