2012-06-28 15 views
5

Mam klasy otoki wokół niektórych obiektów, które chcę użyć jako klucze w mieszanie. Zawinięte i rozwijane obiekty powinny zostać odwzorowane na ten sam klucz.Który test równości używa Ruby's Hash podczas porównywania klawiszy?

Prostym przykładem będzie to:

class A 
    attr_reader :x 
    def initialize(inner) 
    @inner=inner 
    end 
    def x; @inner.x; end 
    def ==(other) 
    @inner.x==other.x 
    end 
end 
a = A.new(o) #o is just any object that allows o.x 
b = A.new(o) 
h = {a=>5} 
p h[a] #5 
p h[b] #nil, should be 5 
p h[o] #nil, should be 5 

Próbowałem ==, ===, eq? i hash wszystko na próżno.

+1

Możecie zajrzeć do 'SimpleDelegator', jeśli chcesz przekazać większość metod na' @ inner'. –

+0

Dzięki @ Marc-AndréLafortune! Nauczyłem się czegoś nowego dzisiaj – alexloh

Odpowiedz

4

Hash używa klucza.eql? przetestować klucze pod kątem równości. Jeśli musisz używać instancji własnych klas jako kluczy w haszowniku, to zaleca się, aby zdefiniować zarówno eql? i metody mieszania. Metoda hash musi mieć wartość i mieć właściwość, że a.eql? (B) implikuje a.hash == b.hash.

Więc ...

class A 
    attr_reader :x 
    def initialize(inner) 
    @inner=inner 
    end 
    def x; @inner.x; end 
    def ==(other) 
    @inner.x==other.x 
    end 

    def eql?(other) 
    self == other 
    end 

    def hash 
    x.hash 
    end 
end 
+0

Ah, więc używa obu. Teraz, kiedy o tym myślę, warto użyć 'hash', aby otrzymać wiadro, a następnie' eql? 'Do faktycznego testu. Myślę, że to samo w Javie – alexloh

+0

Ale dlaczego domyślna implementacja 'eq?' Nie używa '=='? – ony

4

Musisz zdefiniować eql? i hash. Nie znaleziono dokumentacji Hash