2012-06-28 31 views
5

Tengo una clase contenedora alrededor de algunos objetos que quiero usar como claves en un Hash. Los objetos envueltos y desenvueltos deberían corresponder a la misma clave.¿Qué prueba de igualdad utiliza Ruby's Hash al comparar claves?

Un ejemplo sencillo será la siguiente:

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 

He intentado == ===, eq? y hash todo fue en vano.

+1

Es posible que desee ver en 'SimpleDelegator', si desea delegar la mayoría de los métodos a' @ inner'. –

+0

¡Gracias @ Marc-AndréLafortune! Aprendí algo nuevo hoy – alexloh

Respuesta

4

Hash usa key.eql? para probar claves para la igualdad. Si necesita utilizar instancias de sus propias clases como claves en un hash , se recomienda que defina ambos el eql? y métodos hash. El método hash debe tener la propiedad que a.eql? (B) implica a.hash == b.hash.

Entonces ...

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, entonces usa ambos. Ahora que lo pienso, tiene sentido usar 'hash' para obtener el cubo y luego' eql? 'Para la prueba real. Creo que es lo mismo en Java también – alexloh

+0

¿Pero por qué la implementación predeterminada de 'eq?' No usa '=='? – ony

Cuestiones relacionadas