2012-06-28 8 views
5

Ho una classe wrapper attorno ad alcuni oggetti che voglio usare come chiavi in ​​un hash. Gli oggetti wrapper e unwrapper devono essere associati alla stessa chiave.Quale test di uguaglianza utilizza Ruby's Hash quando si confrontano le chiavi?

Un semplice esempio sarà questo:

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 

Ho provato ==, ===, eq? e hash tutto inutilmente.

+1

Si potrebbe voler esaminare 'SimpleDelegator', se si desidera delegare la maggior parte dei metodi per' @ inner'. –

+0

Grazie @ Marc-AndréLafortune! Ho imparato qualcosa di nuovo oggi – alexloh

risposta

4

Hash utilizza key.eql? per testare le chiavi per l'uguaglianza. Se è necessario utilizzare le istanze delle proprie classi come chiavi in ​​un hash, si consiglia di specificare eql? e metodi hash. Il metodo hash deve avere la proprietà che a.eql? (B) implica a.hash == b.hash.

Quindi ...

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, quindi usa entrambi. Ora che ci penso, ha senso usare "hash" per ottenere il bucket, quindi "eql?" Per il test vero e proprio. Penso che sia lo stesso anche in Java – alexloh

+0

Ma perché l'implementazione predefinita di 'eq?' Non usa '=='? – ony

Problemi correlati