ruby变量作为同一个对象(指针?)

>> a = 5 => 5 >> b = a => 5 >> b = 4 => 4 >> a => 5 

如何将’b’设置为’a’,以便在示例中,变量a也将变为4。 谢谢。

 class Ref def initialize val @val = val end attr_accessor :val def to_s @val.to_s end end a = Ref.new(4) b = a puts a #=> 4 puts b #=> 4 a.val = 5 puts a #=> 5 puts b #=> 5 

当你执行b = ab指向与b相同的对象(它们具有相同的object_id )。

当你执行a = some_other_thing ,a将指向另一个对象,而b保持不变。

对于Fixnumniltruefalse ,您无法在不更改object_id情况下更改值。 但是,您可以在不更改object_id情况下更改其他对象(字符串,数组,哈希等), 因为您不使用赋值( =

字符串示例:

 a = 'abcd' b = a puts a #=> abcd puts b #=> abcd a.upcase! # changing a puts a #=> ABCD puts b #=> ABCD a = a.downcase # assigning a puts a #=> abcd puts b #=> ABCD 

数组示例:

 a = [1] b = a pa #=> [1] pb #=> [1] a << 2 # changing a pa #=> [1, 2] pb #=> [1, 2] a += [3] # assigning a pa #=> [1, 2, 3] pb #=> [1, 2] 

你不能。 变量保存对值的引用,而不是对其他变量的引用。

以下是您的示例代码正在执行的操作:

 a = 5 # Assign the value 5 to the variable named "a". b = a # Assign the value in the variable "a" (5) to the variable "b". b = 4 # Assign the value 4 to the variable named "b". a # Retrieve the value stored in the variable named "a" (5). 

有关该主题的更深入讨论,请参阅此文章: 按引用传递或按值传递

如前所述,您使用的语法无法完成。 只是把它扔到那里虽然你可以做一个包装类,但这取决于你真正想要做什么

 ruby-1.8.7-p334 :007 > class Wrapper ruby-1.8.7-p334 :008?> attr_accessor :number ruby-1.8.7-p334 :009?> def initialize(number) ruby-1.8.7-p334 :010?> @number = number ruby-1.8.7-p334 :011?> end ruby-1.8.7-p334 :012?> end => nil ruby-1.8.7-p334 :013 > a = Wrapper.new(4) => # ruby-1.8.7-p334 :014 > b = a => # ruby-1.8.7-p334 :015 > a.number = 6 => 6 ruby-1.8.7-p334 :016 > a => # ruby-1.8.7-p334 :017 > b => # 

你可以使用数组:

 a = [5] b = a b[0] = 4 puts a[0] #=> 4 

这个想法是基于这个答案 。

只是为了参考。

 >> a = 5 => 5 >> a.object_id => 11 >> b = a => 5 >> b.object_id => 11 >> b = 4 => 4 >> b.object_id => 9 >> a.object_id => 11 # We did change the Fixnum b Object. >> Fixnum.superclass => Integer >> Integer.superclass => Numeric >> Numeric.superclass => Object >> Object.superclass => BasicObject >> BasicObject.superclass => nil 

我希望这能让我们更好地理解Ruby中的对象。

在您认为要进行直接指针操作的情况下,一种选择是使用哈希,数组和字符串的替换方法。

当你想让一个方法返回一个变量时,这个方法很有用,该方法设置的proc将在以后改变,并且不希望使用包装器对象的烦恼。

例:

 def hash_that_will_change_later params = {} some_resource.on_change do params.replace {i: 'got changed'} end params end a = hash_that_will_change_later => {} some_resource.trigger_change! a {i: 'got changed'} 

对于这种情况,通常可以更好地使用显式对象包装器,但是这种模式对于构建异步内容的规范/测试很有用。

我不是Ruby专家。 但对于一个技术上疯狂的kluge …只有当你每次使用变量时eval通过eval时才能工作:

 >> a = 5 => 5 >> b = :a => :a >> eval "#{b} = 4" => 4 >> eval "#{a}" => 4 >> eval "#{b}" => 4 

请注意,直接使用b仍然会给你:a并且你不能在不在eval中的表达式中使用它:

 >> b => :a >> b + 1 NoMethodError: undefined method `+' for :a:Symbol 

……肯定有很多警告。 比如你必须捕获binding并在更复杂的场景中传递它…

Ruby中的’通过引用传递参数’?

如果您可以将声明点更改为包装器对象,@ Paul.s有一个答案,但是如果您只能控制引用点,那么这是我尝试过的BasicReference类:

 class BasicReference def initialize(r,b) @r = r @b = b @val = eval "#{@r}", @b end def val=(rhs) @val = eval "#{@r} = #{rhs}", @b end def val @val end end a = 5 puts "Before basic reference" puts " the value of a is #{a}" b = BasicReference.new(:a, binding) b.val = 4 puts "After b.val = 4" puts " the value of a is #{a}" puts " the value of b.val is #{b.val}" 

这输出:

 Before basic reference the value of a is 5 After b.val = 4 the value of a is 4 the value of b.val is 4