Which equality test does Ruby's Hash use when comparing keys?

余生长醉 提交于 2019-11-28 00:51:42

问题


I have a wrapper class around some objects that I want to use as keys in a Hash. The wrapped and unwrapper objects should map to the same key.

A simple example will be this:

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

I've tried ==, ===, eq? and hash all to no avail.


回答1:


Hash uses key.eql? to test keys for equality. If you need to use instances of your own classes as keys in a Hash, it is recommended that you define both the eql? and hash methods. The hash method must have the property that a.eql?(b) implies 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



回答2:


You must define eql? and hash.

The documentation of Hash was lacking but has been improved recently.



来源:https://stackoverflow.com/questions/11247000/which-equality-test-does-rubys-hash-use-when-comparing-keys

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!