我是根据预定义的测试创建了这个类
class Roman
include Comparable
ROMAN_NUMBERS = { 1000 => "m", 900 => "cm", 500 => "d", 400 => "cd",
100 => "c", 90 => "xc", 50 => "l", 40 => "xl", 10 => "x", 9 => "ix",
5 => "v", 4 => "iv", 1 => "i" }
def initialize(number)
@number = number
end
def coerce(other)
if Integer === other
[ other, @number ]
else
[ Float(other), Float(@number) ]
end
end
def <=>(n)
@number <=> n
end
def -(n)
Roman.new(@number - n)
end
def to_s
roman = ''
ROMAN_NUMBERS.each do |value, letter|
roman << letter * (@number / value)
@number = @number % value
end
roman
end
end
但我还是失败了
it "should support substraction" do
(Roman.new(5) - Roman.new(3)).should == 2
(Roman.new(4) - Roman.new(1)).should == 3
(Roman.new(4) - 2).should == 2
res = 6 - Roman.new(1)
res.should == 5
(res.kind_of? Roman).should be true
end
问题是,res
是“有点”Fixnum
。怎么可能?如何通过测试?
答案 0 :(得分:2)
问题是6 - Roman.new(1)
与6.-(Roman.new(1))
相同,即它正在调用Fixnum
的内置减法方法。由于Fixnum
不了解您的Roman
课程,因此会调用您的coerce
方法。
但是你定义coerce
在这种情况下返回Fixnum!解决方案是强制使用另一个操作数,而不是self
。
def coerce other
[self.class.new(other), self]
end
但是如果你用你的代码尝试这个,你会得到一个堆栈错误!那是因为它现在将两个操作数强制转换为Roman
的实例,但它仍然不知道如何减去它们。你应该重新定义你的减法方法来处理这些情况。
attr_reader :number
def - n
return Roman.new(@number - n.number) if n.is_a? Roman
Roman.new(@number - n)
end