2012-06-28 4 views
5

Ich habe eine Wrapper-Klasse um einige Objekte, die ich als Schlüssel in einem Hash verwenden möchte. Die eingepackten und nicht verpackten Objekte sollten demselben Schlüssel zugeordnet sein.Welchen Gleichheitstest verwendet Ruby's Hash beim Vergleich von Schlüsseln?

wird ein einfaches Beispiel sein:

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 

Ich habe ==, === versucht, eq? und Hash alles vergebens.

+1

Sie könnten in 'SimpleDelegator' suchen möchten, wenn Sie die meisten Methoden' @ inner' delegieren möchten. –

+0

Danke @ Marc-AndréLafortune! Habe heute etwas Neues gelernt – alexloh

Antwort

4

Hash verwendet key.eql? Schlüssel auf Gleichheit prüfen. Wenn Sie Instanzen Ihrer eigenen Klassen als Schlüssel in einem Hash verwenden müssen, wird empfohlen, dass Sie beide die eql definieren? und Hash-Methoden. Die Hash-Methode muss die Eigenschaft haben, dass a.eql? (B) bedeutet a.hash == b.hash.

So ...

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, so nutzt es beides. Nun, da ich darüber nachdenke, macht es Sinn, 'hash' zu verwenden, um den Bucket zu bekommen, dann' eql' 'für den eigentlichen Test. Ich denke, es ist das gleiche in Java zu – alexloh

+0

Aber warum Standardimplementierung von 'eq?' Nicht '==' verwenden? – ony

Verwandte Themen