如果它具有相同的object_id,为什么更改方法中的值不会影响Ruby中的调用者?

时间:2014-08-18 04:55:05

标签: ruby

我有这个方法:

def change_value(obj)
  puts obj.object_id #70275832194460
  obj = nil
  puts obj.object_id #8
end

obj = "hi there"
puts obj.object_id #70275832194460
change_value(obj)
puts obj.object_id #70275832194460
puts obj #still 'hi there', while I would expect nil.

为什么如果我们传递对象并更改其值,新值不会在方法之外维护?

3 个答案:

答案 0 :(得分:4)

您没有更改对象的值。您正在更改变量的值。虽然它包含String对象"hi there",但它有一个值。当它包含值nil时,它是不同的(正如Nishu指出的那样,nil.object_id显然是非随机的。)

重要的一点是obj change_value内的obj 另一个变量,其中包含与您调用函数的原始def change_value(inner_var) puts inner_var.object_id # points to the same string as outer_var inner_var = nil puts inner_var.object_id # inner_var is nil now; outer_var still same end outer_var = "hi there" puts outer_var.object_id # points to a string change_value(outer_var) puts outer_var.object_id # still points to the string # (only inner_var is nil, and it doesn't exist any more) 相同的引用。当您更改该变量的引用时,它不会反映在您调用该函数的变量中。更容易看出是否更改了变量名称:

{{1}}

答案 1 :(得分:1)

您的方法命名很差。它名为change_value,但它实际上并未更改该值,而是更改了引用。由于Ruby是按值传递,而不是按引用传递,因此更改引用不会对调用者执行任何操作。如果您实际 更改了值,您将能够观察到差异:

def change_value(obj)
  puts obj.object_id #70275832194460

  obj.replace('hi back!')
  puts obj.object_id #70275832194460

  obj = nil
  puts obj.object_id #8
end

obj = 'hi there'
puts obj.object_id #70275832194460

change_value(obj)
puts obj.object_id #70275832194460

puts obj # 'hi back!'

答案 2 :(得分:0)

局部变量的范围在方法定义中。即使您在方法定义中更改了obj,也不会影响其外部的变量。在change_value的方法定义之外,obj仍然引用与之前相同的对象。