Jwo*_*e55 3 ruby string variable-assignment object-identity
首先,我刚刚学习 Ruby,并且有 JavaScript 背景。我有一个问题找不到答案。我有这个例子:
a = 'red'
b = a
b.replace('blue')
b = 'green'
print a
Run Code Online (Sandbox Code Playgroud)
蓝色的
我的问题是:为什么会这样?我知道该设置b = a使它们具有相同的 object_id,因此从技术上讲,同一个变量字符串有两个名称。但我从来没有看到使用这种递归值更改的理由。如果我设置b = a它是因为我想操纵a的值而不改变它。
此外,似乎有时一个方法会修改a,但有时它会导致“b”成为一个新对象。这看起来模棱两可,没有任何意义。
我什么时候会用到这个?重点是什么?这是否意味着我无法将a的值传递到另一个变量而不将任何更改传播回a?
这里的问题不称为递归,并且 Ruby 变量不是递归的(对于该词的任何正常含义 - 即它们不引用自身,并且您不需要递归例程来使用它们)。计算机编程中的递归是指代码直接或间接调用自身,例如包含对自身调用的函数。
在 Ruby 中,所有变量都指向对象。这无一例外 - 尽管有一些内部技巧可以使事情变得更快,但即使编写a=5也会创建一个名为 的变量a并将其“指向”Fixnum对象5- 仔细的语言设计意味着您几乎不会注意到这种情况的发生。最重要的是,数字不能更改(您不能将 a 更改5为 a 6,它们始终是不同的对象),因此您可以认为以某种方式a“包含” a5并且逃脱它,即使技术上a指向5。
不过,使用字符串,可以更改对象。示例代码的分步解释可能如下所示:
a = 'red'
Run Code Online (Sandbox Code Playgroud)
创建一个String内容为“red”的新对象,并将变量指向a它。
b = a
Run Code Online (Sandbox Code Playgroud)
将变量b指向与 相同的对象a。
b.replace('blue')
Run Code Online (Sandbox Code Playgroud)
调用replace所指向的对象上的方法b(也由 所指向的a) 该方法将字符串的内容更改为“蓝色”。
b = 'green';
Run Code Online (Sandbox Code Playgroud)
创建一个String内容为“绿色”的新对象,并将变量指向b它。变量a和b现在指向不同的对象。
print a
Run Code Online (Sandbox Code Playgroud)
指向的 String 对象的a内容为“蓝色”。因此,根据语言规范,一切正常。
我什么时候会用到这个?
每时每刻。在 Ruby 中,您使用变量临时指向对象,以便调用它们的方法。对象是您想要使用的东西,变量是您在代码中用来引用它们的名称。它们是独立的这一事实有时会让您感到困惑(特别是在带有字符串的 Ruby 中,许多其他语言没有这种行为)
这是否意味着我无法将“a”的值传递到另一个变量而不需要递归回“a”进行任何更改?
如果你想复制一个字符串,有几种方法可以做到。例如
b = a.clone
Run Code Online (Sandbox Code Playgroud)
或者
b = "#{a}"
Run Code Online (Sandbox Code Playgroud)
然而,在实践中,您很少只想直接复制字符串。您将想做一些与代码目标相关的其他事情。通常在 Ruby 中,会有一个方法来执行您需要的操作并返回一个新的String,因此您可以执行以下操作
b = a.something
Run Code Online (Sandbox Code Playgroud)
在其他情况下,您实际上希望对原始对象进行更改。这完全取决于您的代码的目的是什么。对 String 对象进行就地更改可能很有用,因此 Ruby 支持它们。
此外,有时一个方法似乎会递归到“a”,有时它会导致“b”成为一个新的object_id。
但事实并非如此。没有方法会改变对象的身份。然而,大多数方法将返回一个新对象。有些方法会更改对象的内容 - 您需要更加了解 Ruby 中的那些方法,因为可能会更改其他地方使用的数据 - 其他 OO 语言也是如此,JavaScript 对象也不例外,它们的行为以完全相同的方式。