在阅读了Is ruby pass by reference or value?之后,我学到了很多东西,但是我的问题比读之前要多(我认为这很好)。
请考虑以下示例
def foo(bar)
bar = 'reference'
end
baz = 'value'
foo(baz)
puts "Ruby is pass-by-#{baz}"输出 Ruby is pass-by-value
这里是我试图剖析这是如何工作的:
首先,在全局范围内,baz具有value值。
现在,foo接受一个参数,不管您传递给它什么,都是在local级别上。
因此,当我们传入baz时,还有另一个baz,它等于reference,但这是在本地级上,因此,当我们将它放到全局级别上时,它会打印value。
现在考虑另一个示例
def foo(bar)
bar.replace 'reference'
end
baz = 'value'
foo(baz)
puts "Ruby is pass-by-#{baz}"输出
Ruby is pass-by-reference
如果我上面说的是真的,这里的.replace方法会改变全局baz吗?我解释得对吗?请随时指出我的尝试中的任何错误,我不知道我是否在正确的轨道上。
谢谢!
编辑
更多的魔术
def my_foo(a_hash)
a_hash["test"]="reference"
end;
hash = {"test"=>"value"}
my_foo(hash)
puts "Ruby is pass-by-#{hash["test"]}"发布于 2016-08-31 13:42:02
Ruby是逐值传递的,但是这些值是对对象的引用。
在您的第一个实验中,baz是对字符串"value"的引用。当调用bar时,foo被初始化为baz的副本(即引用的副本)。然后,使用对字符串bar的引用覆盖"reference"。因为bar是一个副本,所以覆盖它不会改变baz。
在第二个实验中,baz是对字符串"value"的引用,bar在调用foo时被初始化为baz的副本。这一次,您不会覆盖bar,而是在它上调用一个方法。尽管bar是baz的副本,但它们引用的对象是同一个对象(字符串"value")。调用该方法将更改该对象的状态。然后在baz上调用baz(通过将其替换为"Ruby is pass-by-#{baz}"间接调用),to_s返回新的状态。
你的第三个实验很像第二个实验。在该方法中,您更改引用副本所引用的对象的状态,然后,在该方法之外,通过原始引用读取新状态。
发布于 2016-08-31 13:42:49
很有趣的事。
玩object_id,你会看到红宝石在下面的场景中所做的事情:
def foo(bar)
puts bar.object_id
bar = 'reference'
puts bar.object_id
end
baz = 'value'
puts baz.object_id
foo(baz)输出
> baz = 'value'
=> "value"
> puts baz.object_id
70241392845040
> foo(baz)
70241392845040
70241392866940在本地赋值bar = 'reference'之后,局部变量bar将引用另一个对象,因此不会更改原始对象。
在某些情况下,它似乎会使您的对象成为dup。
发布于 2016-08-31 13:45:29
也许这将有助于理解它:
x = 'ab'
x.object_id
=> 70287848748000 # a place in memory
x = 'cd'
x.object_id
=> 70287848695760 # other place in memory (other object)
x.replace('xy')
x.object_id
=> 70287848695760 # the same place in memory (the same object)https://stackoverflow.com/questions/39250963
复制相似问题