我已经为测试编写了两个ruby文件
test.rb:
#!/usr/bin/ruby
def foo(bar)
bar['key'] = 'value'
end
def my_print(a)
a.each{|k,v|
puts "#{k} => #{v}"
}
end
test_drive.rb:
#!/usr/bin/ruby
require 'test.rb'
hash_test = Hash.new
foo(hash_test)
my_print(hash_test)
它的效果与我的预期一致,输出为
key =>值
但是当我将test.rb归为
时#!/usr/bin/ruby
def foo(bar)
pre_defined = {'key' => 'value'}
bar = pre_defined
end
def my_print(a)
a.each{|k,v|
puts "#{k} => #{v}"
}
end
这里我使用了预定义的哈希值,但现在它没有输出任何内容。 “hash_test”现在是一个空哈希。 请说明为什么会发生这种情况?
答案 0 :(得分:3)
这是一个简单的答案:
在ruby中,您通过引用传递带有对象的变量。将Object分配给变量时,该变量实际上并不包含Object本身。相反,它只包含对该对象的引用。
可能有助于您开始查看引用和对象之间的差异,以便了解如何将变量作为参数发送:Object本身不驻留在变量中,变量指向内存中Object的引用因此,如果一个变量指向另一个对象并对其进行修改,那并不意味着它修改了之前引用的Object。
重要的是你要理解的是foo方法中的bar参数实际上只是对内存中Object的引用,而不是Object本身。因此,如果bar一旦指向Object,但它现在引用另一个Object,它将修改它引用的内容,而不是它指向的前一个对象。这是最后一次测试的代码.rb略微评论,以便您更好地理解它:
def foo(bar) # here "bar" points to the same object as "hash_test"
pre_defined = {'key' => 'value'} # here a new object is created and referenced
bar = pre_defined # now "bar" points to a new object and forgets about "hash_test"
end
def my_print(a) # here "a" holds a reference to "hash_test" which is empty
a.each{|k,v| # "a" is empty, so it has nothing to put
puts "#{k} => #{v}"
}
end
我希望这会有所帮助。如果你需要更详细的东西:
您的上一版test.rb在test_drive.rb中打印空哈希的原因是因为引用“hash_test”指向的哈希对象根本没有被修改。相反,foo方法虽然最初作为参数“bar”接收“hash_test”所指向的哈希对象的引用,但很快用“bar”中的引用替换了对全新哈希对象的全新引用“ pre_defined“变量指向。现在“bar”不指向与“hash_test”相同的Object,因此“hash_test”指向的Object永远不会被修改。因此,“hash_test”包含的哈希对象从未真正填充任何内容,并且当my_print尝试打印时为空。
答案 1 :(得分:1)
也就是说,因为Ruby是通过值传递的,所以传递了对象的引用。这与Java的行为类似。这意味着您只有foo方法中的引用副本,并且重新分配它不会更改此方法之外的引用。
更详细: 在你的第一个例子中,你将哈希传递给你的foo方法。引用将被复制,因此在foo方法中,您有一个引用的副本,该副本指向与'hash_test'相同的对象,但不是同一个。因此,调用Hash方法会更改方法之外的对象的值。但是在你的第二个例子中你没有改变给定Hash的值,你将一个新的Hash对象分配给方法引用的副本,这对'hash_test'引用没有影响。