Ruby Koans - 数组填充方法会影响它的返回方式

时间:2017-08-18 13:40:18

标签: arrays ruby

我一直在研究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仅在某些情况下按值传递吗?我是否误解了传值/参考甚至意味着什么?我的问题与传值/参考完全无关吗?

1 个答案:

答案 0 :(得分:0)

您可以在ruby中看到对象作为数据的引用。 因此,即使Ruby 按值传递,复制的东西也是对象,a.k.a是一个强调数据的句柄。

即使从您链接到的答案,也说过:

  

变量始终是对象的引用。为了获得一个不会从你下面改变的对象,你需要复制或克隆你传递的对象,从而给出一个没有其他人可以引用的对象。 (尽管这不是防弹的 - 但两种标准克隆方法都做了浅拷贝,因此克隆的实例变量仍然指向与原件相同的对象。如果ivars引用的对象发生变异,那么仍然显示在副本中,因为它引用了相同的对象。)