eql? behavior after redefining Object#hash

Ruby API says:

The eql? method returns true if obj and other refer to the same hash key.

I changed the hash method for Object :

class Object
 def hash
   1
 end
end

Object.new.hash == Object.new.hash
# => true

Object.new.eql? Object.new
# => false

I don't understand why the second statement returns false ; according to Ruby Object API above, it should return true .


This is a documentation bug. You read it correctly, but the documentation is contradictory.

  • On the one hand, the documentation says:

    The eql? method returns true if obj and other refer to the same hash key.

    from which you can expect as you did in your question:

    Object.new.eql? Object.new
    # => true
    
  • On the other hand, it also says:

    For objects of class Object, eql? is synonymous with ==.

    where the definition of == is given as:

    At the Object level, == returns true only if obj and other are the same object.

    It logically follows that:

    For objects of class Object, eql? returns true only if obj and other are the same object.

    from which you should expect:

    Object.new.eql? Object.new
    # => false
    
  • So the documentation makes contradictory claims. You relied on one of them, and made an expectation, but looking at the actual result, the reality seems to support the second claim.


    That's not what the docs say, and "the same hash key" isn't really relevant to the code you post.

    hash creates a hash key, with the implication that a.eql?(b) means a.hash == b.hash . That's different than breaking hash and expecting an unmodified eql? to work the way you expect.

    eql? must be overridden to provide the semantics you want, eg, a custom class could override eql? to provide a domain-specific equivalency. The above hash contract implications would still need to be followed if you want other code to work appropriately.

    (This is similar to the Java mantra "override hashCode if you override equals , eg, http://www.xyzws.com/javafaq/why-always-override-hashcode-if-overriding-equals/20.)


    You're creating two new objects, they will never be the same.

    a = Object.new
    => #<Object:0x007fd16b35c8b8>
    b = Object.new
    => #<Object:0x007fd16b355540>
    

    And I will refer you back to this SO question

    链接地址: http://www.djcxy.com/p/58488.html

    上一篇: 其他NaN值是什么?

    下一篇: EQL? 重新定义Object#hash后的行为