我正在做一个预先写好测试的练习。起初,测试似乎在类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
方法的范围方面遇到了根本性的错误?
备注
我不是学生,这是我自己做的事情。
目前我已将@@multiples
定义为全局变量,因为我需要在initialize
和to
中访问它 - 如果我的错误范围可能会改变。
对于那些想要了解的人 - 本练习的目的是编写一个程序,给定一个数字,可以找到所有3或5的倍数之和但不包括该数字的总和。我们还必须允许程序配置为找到的倍数之和 3和5以外的数字。
遵循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]>
方法的范围以及测试正在寻找的内容仍然非常非常困惑。
答案 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
所以不要全力以赴,因为这是一个练习:尝试将其作为实例变量并首先解决第二种情况。然后使用动态创建的实例编写静态方法。