这两段代码有什么区别?

时间:2014-03-04 08:28:09

标签: ruby oop immutability

这会打印1

def sum(i)
  i=i+[2]
end

$x=[1]
sum($x)
print $x

这会打印12

def sum(i)
  i.push(2)
end

$x=[1]
sum($x)
print $x

后者正在修改全局变量$x。为什么在第二个例子中修改它而不是在第一个例子中?这会发生在类push的任何方法(不仅仅是Array)吗?

3 个答案:

答案 0 :(得分:4)

在第一个代码段中,您指定新的局部变量来保存返回的$x + [2]操作的结果,但它不会更改$x(因为+方法不会修改接收者对象)。在您的第二个剪辑中,您使用Array#push方法修改对象(在这种情况下,对象分配给$x全局变量并作为i传递到您的sum方法中它被称为。

答案 1 :(得分:4)

变量范围与此无关。

在第一个代码中,您只使用赋值运算符i分配给变量=,而在第二个代码中,您正在修改$x(也称为{ {1}})使用破坏性方法i。分配永远不会修改任何对象。它只提供一个引用对象的名称。方法是破坏性的或非破坏性的。像pushArray#push这样的破坏性方法会修改接收器对象。像String#concatArray#+这样的非破坏性方法不会修改接收器对象,而是创建一个新对象并返回该对象,或者返回一个已存在的对象。

回答您的评论

是否可以修改接收器取决于接收器对象的类。对于数组,散列和字符串等,据说是 mutable ,可以修改接收器。对于被称为 immutable 的数字等,不可能这样做。

答案 2 :(得分:1)

i.push(2)2追加到i指向的数组。由于这是$x指向的相同数组,$x也会附加2

i=i+[2]创建一个 new 数组并将i设置为它 - 现在这是一个与$x指向的数组不同的数组。