1
class Foo
  def bar
    @instance_variable = [['first']]

    # make a duplicate object with the :dup method
    local_variable=@instance_variable.dup

    # They have different object_id
    p @instance_variable.object_id
    p local_variable.object_id


    local_variable.each{|n|n.push('second')}
    @instance_variable
  end
end

f=Foo.new
p f.bar

=> 2000
=> 2002
=> [["first", "second"]]

似乎 local_variable 仍然引用@instance_variable,尽管它是一个不同的对象。这种行为在每个块中都有pushunshift使用像这样的正常分配local_variable='second',结果符合预期=> [['first']]

不明白为什么local_variable.each{|n|n.push('second')}会影响@instance_variable

使用 Ruby-1.9.2p318

4

2 回答 2

2

Both local_variable and @instance_variable have references to the same object, the inner array ['first']. And because it's a mutable Array, you can effect changes to one array through the other.

Object#dup in Ruby provides a shallow copy. In order to make a deep copy of an Array, you'd need to write some code (or find a library) that recursively walks the data structure, deep-cloning its pieces of mutable state.

于 2013-02-10T23:26:14.713 回答
1

问题是您没有测试正确的对象。你说:

p @instance_variable.object_id
p local_variable.object_id

但这不是你要推动的对象。试试这个:

p @instance_variable[0].object_id
p local_variable[0].object_id

它们同一个对象。

换句话说,更改的情况并非如此,而是恰好它们都包含对同一对象的引用,因此显然更改一个指向对象会更改另一个指向的对象。local_variable@instance_variable

于 2013-02-10T23:30:06.960 回答