如果我这样做
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
,当我将z
分配给20
时,x
和y
保留了值1
。对于Arrays
,即使我仅将值分配给c[]
,更改也会反映在a
,b
中。 Array
s发生了什么?
答案 0 :(得分:1)
使用z = 20
,您将更改z
以引用其他对象
使用c[0] = 'a'
,您正在更改a
和b
也引用的原始对象。
答案 1 :(得分:1)
考虑将哪些对象分配给哪些变量,毕竟变量只是对象的句柄。在ruby中,一切都是一个对象,变量就是你与它们交互的方式。
因此...
a = b = 1
这会将a
和b
设置为引用同一个对象。如果我后来说:
a = 2
然后我设置a
来引用一个新对象,它根本不会影响b
,这仍然是1
。该插件只需一个简单的步骤。
a
设置为对象2
。但是,遵循这个逻辑:
a = b = []
同样,a
和b
引用同一个对象。这次是阵列。但现在我们这样做了:
a[0] = 'hello'
我们这里有不同的情况。您根本没有更改对象a
引用。您正在查找对象a
引用,然后修改该对象。
考虑一下口译员会做什么。执行该行时将执行以下步骤。
a
引用的对象(恰好是b
引用的同一对象)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')
我指出这一点只是因为当表达为方法的调用时,我们很清楚我们在这里修改现有对象。
答案 2 :(得分: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