2013-04-04 1 views
2

Я реализовал сопоставимый и перечислим, так что я могу использовать сравнение и включает в себя:Как сравнить класс с любым другим произвольным классом через include? Метод

Учитывая простой класс ниже:

class Card 
    include Comparable 
    include Enumerable 
    attr_accessor :value 

    def initialize(v) 
    @value = v 
    end 

    def <=>(other) 
    @value <=> other.value 
    end 

    def each 
    yield @value 
    end 
end 

Тогда:

c = Card.new(1) #so right now we have @value at 1 

Ни один из них включает в себя методы работы хотя:

[1,3,4,5].include?(c) 
c.include?([1,3,4,5]) 

Is это вообще возможно использовать метод include для этого? Я знаю, что могу сделать это по-другому, но я бы хотел сделать это «рубин». (Предполагая, что это даже рубин, как способ ...) Я просто попал в рубин из java и C++

Заранее спасибо!

ответ

1

Если вы достаточно долго смотрите на свой код, вы увидите. Вы внедряете оператора космического корабля, который предполагает, что other является Card. Но вы вызываете его на Fixnums! Вам нужно сделать небольшую проверку:

class Card 
    include Comparable 
    include Enumerable 

    attr_accessor :value 
    def initialize(v) 
    @value = v 
    end 
    def <=>(other) 
    if other.is_a?(Card) 
     @value <=> other.value 
    else 
     @value <=> other 
    end 
    end 

    def each 
    yield @value 
    end 
end 

c = Card.new(1) 

[1,3,4,5].include?(c) # => true 
c.include?([1,3,4,5]) # => false # because 1 does not contain an array [1, 2, 3, 4, 5] 
+0

Включает ли 'include?' Внутренние вызовы '<=>'? –

+0

@ArupRakshit Да. Объект Array имеет метод 'include?'. Когда вы вызываете 'some_array.include? (Item)', проверяется класс для 'item', поэтому может использоваться правильный' <=>''. Начиная с 'item.class == Card' вместо этого используется переопределенный компаратор. Оптимально, потому что он позволяет сравнивать карту по атрибутам, а не по ошибке в 'ArgumentError: сравнение карты с картой не удалось – onebree