0

这种行为正确吗?我正在运行如下代码:

@a_hash = {:a => 1}
x = @a_hash
x.merge!({:b => 2})

最后,x 的值已按预期更改,但 @a_hash 的值也已更改。我得到 {:a => 1, :b => 2} 作为它们两个的值。这是Ruby中的正常行为吗?

4

3 回答 3

4

是的,实例变量@a_hash和局部变量x存储对同一实例的引用Hash,当您更改此实例时(使用merge!更改对象的 mutator 方法),这些变量将被评估为相同的值。

您可能希望使用merge创建对象副本而不更改原始对象的方法:

@a_hash = {:a => 1}
x = @a_hash
y = x.merge({:b => 2})
# y => {:a => 1, :b => 2}
# x and @a_hash => {:a => 1}
于 2012-02-03T19:46:53.093 回答
3

@a_hash 是 x 的链接。所以如果你不想改变@a_hash,你应该这样做:

@a_hash = {:a => 1}
x = @a_hash.clone
x.merge!({:b => 2})
于 2012-02-03T19:48:39.267 回答
1

是的,这是 ruby​​(和大多数其他语言)中的正常行为。两者x@a_hash都是对同一对象的引用。通过调用merge!您更改该对象,并且该更改通过引用它的所有变量可见。

如果您不希望这种行为,您不应该使用变异方法(即x = x.merge(...)改用)或在变异之前复制对象(即x = @a_hash.dup)。

于 2012-02-03T19:49:00.140 回答