我正在使用Ruby Koans,以便更好地掌握Ruby和TDD。我在about_hashes.rb
的代码中得到了第93行,这让我很困惑如何将它铲入默认构造函数而不是哈希值。出于好奇,我尝试使用与字符串相同的东西作为构造函数的参数,它产生了类似的结果。
现在我的问题是为什么,无论我使用什么密钥,都会检索相同的对象,以及如何在方法中的哈希中的特定键上将新对象铲入数组 {{1 }}的吗
test_default_value_is_the_same_object
答案 0 :(得分:3)
原因在于测试名称。
test_default_value_is_the_same_object
可以告诉您,当您要求hash[:some_value_that_doesnt_exist_yet]
时,默认情况下会返回您指定的默认值 - 每个相同的对象时间。通过修改该对象,可以为每个不存在的键修改它。修改hash[:one]
也会修改hash[:two]
。
test_default_value_with_block
显示使用块构造哈希,该块将用于为每个键提供新值。当你这样做时,hash[:one]
和hash[:two]
的值是不同的。
答案 1 :(得分:2)
当密钥不存在时,您已创建一个新的Hash
,其中Array
为累加器,因此
hash = Hash.new([])
hash[:one] << "uno"
hash[:one] == ["uno"] #=> true
但是
hash[:two] << "dos"
(hash[:one] == hash[:two]) && (hash[:two] == ["uno","dos"]) #=> true
hash[:three] == ["uno","dos"] #=> true
因为["uno","dos"]
是使用Hash
和hash[:non_existant_key]
指向它创建的原始数组。
注意:在这种情况下,hash
实际上没有添加任何密钥。它类似于
a = []
hash = {}
hash.fetch(:one,a) << 'uno'
hash.fetch(:two,a) << 'dos'
hash.fetch(:three, a)
#=> ['uno','dos']
hash
#=> {}
要解决此问题,您可以使用第二次测试中提到的语法
hash = Hash.new {|h,k| h[k] = [] }
这意味着每个新密钥都会将新的Array
实例化为其值,而不是一遍又一遍地重复使用相同的Array
当Hash.new(obj)
是一个可变对象时,这是obj
语法的问题