明白了吗?常量被附加到局部变量的同时。
不,它没有附加到,局部变量也没有。
常量和局部变量都引用的单个对象被附加到,但是常量和局部变量都没有改变。您不能在 Ruby 中修改或更改变量或常量(至少不是以您的问题暗示的方式),您可以唯一更改的是对象。
您可以对变量或常量做的唯一两件事是取消引用并分配给它们。
这里的常数是一个红鲱鱼,它与给出的例子完全无关。唯一相关的是整个示例中只有 一个 单个对象。可以使用两个不同的名称访问该单个对象。如果对象改变了,那么对象就改变了。时期。它并没有神秘地将自己一分为二。您使用哪个名称来查看更改的对象并不重要。反正只有一个对象。
这与在任何其他编程语言中的工作方式完全相同:如果您在 Python、Java、C#、C++、C、Lisp、Smalltalk、JavaScript、PHP、Perl 或其他语言中对可变对象有多个引用,那么无论使用什么引用,对该对象的任何更改都将是可见的,即使其中一些引用是 final 或 const 或该特定语言所称的任何内容。
这就是共享可变状态的工作原理,也是共享可变状态不好的众多原因之一。
在 Ruby 中,您通常可以对任何对象调用 freeze 方法以使其不可变。然而,再一次,您在这里修改了 object,所以任何其他引用该对象的人都会突然发现该对象已变为不可变。因此,为了安全起见,您需要首先通过调用dup 来复制对象。但是当然,这也是不够的,如果你想到一个数组,例如:如果你dup这个数组,你会得到一个不同的array,但是里面的对象 该数组与原始数组中的数组相同。如果你freeze数组,那么你就不能再修改数组,但是数组in中的对象很可能仍然是可变的:
ORIG = ['Hello']
CLONE = ORIG.dup.freeze
CLONE[0] << ', World!'
CLONE # => ['Hello, World!']
这对你来说是共享的可变状态。摆脱这种疯狂的唯一方法是放弃共享状态(例如 Actor 编程:如果没有其他人可以看到它,那么它改变的频率或时间并不重要)或可变状态(即函数式编程:如果它永远不会改变,那么有多少人看到它并不重要)。
原始示例中的两个变量之一实际上是常数这一事实与问题完全无关。 Ruby 中的变量和常量有两个主要区别:它们有不同的查找规则,如果常量被多次分配,它们会产生警告。但是在这个例子中,查找规则是无关紧要的,并且常量只分配了一次,所以在这种情况下,变量和常量之间确实没有区别。