方法范围 - 不确定方法应该是实例还是类方法

时间:2015-08-20 10:05:46

标签: ruby scope

我正在做一个预先写好测试的练习。起初,测试似乎在类to的实例上调用一个名为SumOfMultiples的方法,如下所示:

  def test_sum_to_1000
    assert_equal 233_168, SumOfMultiples.to(1000)
  end

因此,我写了我的课程如下:

class SumOfMultiples
  @@multiples = [3, 5]

  def initialize *multiples
    @@multiples = multiples unless multiples.empty?
  end

  def self.to num
    sum  = 0

    (0..num-1).each { |e| sum += e if (@@multiples.any? { |m| e % m == 0 }) }
    sum
  end
end

现在,我遇到了直接在to上致电SumOfMultiples的测试:

  def test_configurable_7_13_17_to_20
    assert_equal 51, SumOfMultiples.new(7, 13, 17).to(20)
  end

上面的测试失败了,因为我将to定义为实例方法,这是使先前的测试通过所需的。我是否在to方法的范围方面遇到了根本性的错误?

备注

  1. 我不是学生,这是我自己做的事情。

  2. 目前我已将@@multiples定义为全局变量,因为我需要在initializeto中访问它 - 如果我的错误范围可能会改变。

  3. 对于那些想要了解的人 - 本练习的目的是编写一个程序,给定一个数字,可以找到所有3或5的倍数之和但不包括该数字的总和。我们还必须允许程序配置为找到的倍数之和 3和5以外的数字。

  4. 遵循Alex Tetzlaff的建议后

    我已经更改了@multiples的范围,因此它是一个实例变量。起初我跳过除了test_configurable_7_13_17_to_20之外的所有测试,我改变了to的范围,以便它是一个实例方法 - 一切都通过了

    然后我尝试再次运行test_sum_to_1000 - 它失败了,因为它看不到@multiples

    接下来,我将to的范围更改回类方法,现在它已self.to,我通过调用@multiples设置self.class.new - 所以我的{{1} } class现在看起来像:

    SumOfMultiples

    class SumOfMultiples @multiples = [3, 5] def initialize *multiples @multiples = multiples unless multiples.empty? end def self.to num self.class.new sum = 0 (0..num-1).each { |e| sum += e if (@multiples.any? { |m| e % m == 0 }) } sum end end 现在因test_configurable_7_13_17_to_20

    而失败

    TL; DR我对undefined method 'to' for #<SumOfMultiples:0x000000010b0198 @multiples=[7, 13, 17]>方法的范围以及测试正在寻找的内容仍然非常非常困惑。

1 个答案:

答案 0 :(得分:1)

将@@ multiples存储为全局或更精确的“类变量”是一个主要的设计缺陷。

initialize将被多次调用,并且每次都会改变所有实例的to - 方法的行为。

 def test_configurable_7_13_17_to_20
    sm1= SumOfMultiples.new(7, 13, 17)
    sm2=SumOfMultiples.new(1,2,4)
    assert_equal 51, sm1.to(20) # will probably fail
 end

所以不要全力以赴,因为这是一个练习:尝试将其作为实例变量并首先解决第二种情况。然后使用动态创建的实例编写静态方法。