2014-01-31 23 views
-1

类的平等,我创建这个类基于预定义的测试与强制

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。那可能怎么样?如何使其通过测试?

回答

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 
+0

谢谢你的帮助,主要是为了解释:) –