>> a = 5
=> 5
>> b = a
=> 5
>> b = 4
=> 4
>> a
=> 5
如何将'b'设置为实际为'a',以便在示例中,变量a也将变为4。感谢。
答案 0 :(得分:6)
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 = a
时,b
指向与a
相同的对象(它们具有相同的object_id
)。
执行a = some_other_thing
时,a会指向另一个对象,而b
保持不变。
对于Fixnum
,nil
,true
和false
,您无法在不更改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
p a #=> [1]
p b #=> [1]
a << 2 # changing a
p a #=> [1, 2]
p b #=> [1, 2]
a += [3] # assigning a
p a #=> [1, 2, 3]
p b #=> [1, 2]
答案 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).
有关该主题的更深入讨论,请参阅此文章:pass by reference or pass by value。
答案 2 :(得分:1)
正如已经注意到的,您正在使用的语法无法完成。只是把它扔到那里虽然你可以做一个包装类,但这取决于你真正想要做什么
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)
=> #<Wrapper:0x100336db8 @number=4>
ruby-1.8.7-p334 :014 > b = a
=> #<Wrapper:0x100336db8 @number=4>
ruby-1.8.7-p334 :015 > a.number = 6
=> 6
ruby-1.8.7-p334 :016 > a
=> #<Wrapper:0x100336db8 @number=6>
ruby-1.8.7-p334 :017 > b
=> #<Wrapper:0x100336db8 @number=6>
答案 3 :(得分:1)
答案 4 :(得分:1)
仅供参考。
>> 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中的对象。
答案 5 :(得分:1)
如果您觉得自己想要直接指针操作,可以使用Hashes,Arrays&amp; amp;的替换方法。字符串。
当你想让一个方法返回一个变量时,这个方法很有用,该方法设置的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'}
对于这种情况,通常可以更好地使用显式对象包装器,但是这种模式对于构建异步内容的规范/测试很有用。
答案 6 :(得分:0)
我不是Ruby专家。但是对于一个技术上疯狂的kluge ......只有当你每次使用变量时都想通过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
并在更复杂的场景中传递它...
'pass parameter by reference' in 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