EQL? 重新定义Object#hash后的行为

Ruby API说:

eql? 方法返回true如果obj和其他引用相同的散列键。

我改变了Object的哈希方法:

class Object
 def hash
   1
 end
end

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

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

我不明白为什么第二个陈述返回false ; 根据上面的Ruby Object API,它应该返回true


这是一个文档错误。 你读得对,但文件是矛盾的。

  • 一方面,文件说:

    eql? 方法返回true如果obj和其他引用相同的散列键。

    从中你可以期待你的问题:

    Object.new.eql? Object.new
    # => true
    
  • 另一方面,它也说:

    对于Object类的对象,eql? 与==同义。

    ==的定义如下给出:

    在Object级别,==只有在obj和其他对象相同时才返回true。

    它在逻辑上遵循:

    对于Object类的对象,eql? 仅当obj和其他对象相同时才返回true。

    您应该从中期望:

    Object.new.eql? Object.new
    # => false
    
  • 所以文件做出矛盾的说法。 你依靠其中一个,并作出了期望,但看看实际结果,现实似乎支持第二个要求。


    这不是文档所说的,“相同的哈希键”与您发布的代码并不真正相关。

    hash会创建一个哈希键,其含义是a.eql?(b)表示a.hash == b.hash 。 这不同于打破hash和期待未经修改的eql? 以您期望的方式工作。

    eql? 必须重写以提供所需的语义,例如,自定义类可以覆盖eql? 提供特定领域的等同性。 如果您希望其他代码正常工作,上述hash合同影响仍需要遵循。

    (如果你覆盖equals ,这与Java口头禅重写hashCode类似,例如http://www.xyzws.com/javafaq/why-always-override-hashcode-if-overriding-equals/20。)。


    您正在创建两个新对象,它们永远不会相同。

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

    我会把你推荐给这个SO问题

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

    上一篇: eql? behavior after redefining Object#hash

    下一篇: C# .Equals(), .ReferenceEquals() and == operator