我一直在研究Ruby Koans,而且我已经完成了这个部分,我不太了解。具体来说,它是about_dice_project,他们要求我们定义一个类来传递几个预先设置的测试。最初,我的班级看起来像
class DiceSet
attr_accessor :values
def initialize
@values = []
end
def roll(num)
num.times { |i| @values[i] = rand(1..6) }
return @values
end
end
但这未通过下面的测试
dice = DiceSet.new
dice.roll(5)
first_time = dice.values
dice.roll(5)
second_time = dice.values
assert_not_equal first_time, second_time,
"Two rolls should not be equal"
我在一些测试后发现first_time和second_time都有相同的object_id。所以我查看了stackoverflow以获得一些帮助,并找到了this answer,它没有直接回答我的问题,但我确实发现我们的代码存在重大差异;即,而不是使用" num.times"滚动骰子的方式,改为
@values = Array.new(num) { rand(1..6) }
这确实通过了上述测试。
在找到这个之后,我试图弄清楚为什么我的原始代码不起作用,所以我认为Ruby可能是通过引用传递的,这就是为什么当骰子滚动方法创建了一个新数组,而不是修改现有数组,这是一个创建的新对象ID。但后来我找到了this question,它说Ruby是按值传递的,如果是这样,那么我原本期望我的原始方式可行。
所以现在我又感到困惑了,我想问一下 - 我的想法出了什么问题? Ruby仅在某些情况下按值传递吗?我是否误解了传值/参考甚至意味着什么?我的问题与传值/参考完全无关吗?
答案 0 :(得分:0)
您可以在ruby中看到对象作为数据的引用。 因此,即使Ruby 按值传递,复制的东西也是对象,a.k.a是一个强调数据的句柄。
即使从您链接到的答案,也说过:
变量始终是对象的引用。为了获得一个不会从你下面改变的对象,你需要复制或克隆你传递的对象,从而给出一个没有其他人可以引用的对象。 (尽管这不是防弹的 - 但两种标准克隆方法都做了浅拷贝,因此克隆的实例变量仍然指向与原件相同的对象。如果ivars引用的对象发生变异,那么仍然显示在副本中,因为它引用了相同的对象。)