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值是什么?