1

如果我这样做

x = y = z = 1
z = 20

然后我得到

"#{x}----#{y}----#{z}"
# => "1----1----20" 

现在,如果我做这样的事情:

a = b = c = []

然后我得到这个:

"#{a}-----#{b}-----#{c}"
# => "[]-----[]-----[]"

但是,如果我执行以下操作:

c[0] = 'a'
c[1] = 'b'
c[2] = 'c'

我明白了:

"#{a}-----#{b}-----#{c}"
# => "[\"a\", \"b\", \"c\"]-----[\"a\", \"b\", \"c\"]-----[\"a\", \"b\", \"c\"]"

如果是x, y, z, 当我分配z20, 然后xy保留该值1。对于Arrays,即使我c[]只为 赋值,更改也反映在a,中b。s怎么了Array

4

3 回答 3

1

想想什么对象被分配给什么变量,毕竟变​​量只是一个对象的句柄。在 ruby​​ 中,一切都是对象,变量就是你与它们交互的方式。

所以...

a = b = 1

这设置ab引用相同的对象。如果我以后说:

a = 2

然后我设置a引用一个新对象,它根本不应该影响b,它仍然很高兴1。解释者采取了一个简单的步骤。

  1. 将局部变量设置a为对象2

但是,按照这个逻辑:

a = b = []

再次,ab引用同一个对象。这次是数组。但是现在当我们这样做时:

a[0] = 'hello'

我们这里有一个不同的场景。您根本没有更改对象a引用的内容。您正在查找对象a引用,然后修改该对象。

想想口译员会做什么。执行该行时将采取以下步骤。

  1. 找到被引用的对象a(恰好是被引用的同一个对象b
  2. 0将该对象索引处的值设置为字符串"hello"

这就是说简单的局部变量赋值,如:

a = 1

当存在这样的间接层时,操作会有所不同:

a[0] = 'hello'
a.foo = 'bar'
a.set_value 'some val'

或者考虑在数组中设置一个值,就像在该数组上调用一个方法一样。因此,如果您认为差异变得更容易掌握a[0] = 'foo'

a.set_value(0, 'foo')

像这样的事情实际上是在 ruby​​ 数组中发生的。原来为数组索引分配一个值会调用该[]=(index, value)方法。这些都是有效的和等效的。

a[0] = 'foo'
a.[]=(0, 'foo')
a.send('[]=', 0, 'foo')

我指出这一点只是因为当表达为一个方法的调用时,很明显我们在这里修改了一个现有的对象。

于 2012-10-07T08:40:23.497 回答
1

使用z = 20,您将更z改为引用另一个对象,

使用,您正在更改同时引用c[0] = 'a'的原始对象。ab

于 2012-10-07T08:28:16.483 回答
0

在 Ruby 中,你有改变它的对象的方法和返回新对象的方法(方法的文档会提到这一点)。整数不能变异:二永远是二。玩弄 object_id 可以解决问题:

puts 1.object_id # 3
a = 1
puts a.object_id # 3
puts 20.object_id # 41
a = 20
puts a.object_id # 41

b = []
puts b.object_id # a number
b[1]=1 # mutating object
puts b.object_id # same number
b = b+[2] # the + method results in new object http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-2B
puts b.object_id # another number
于 2012-10-07T13:30:20.897 回答