Override `#hash` when overriding `#eql?`
In my notes here, I’ve written that #hash
must be overridden when overriding #eql?
. I was unsure why this was the case.
What is #hash
?
I see in pry that all objects respond to #hash
:
> 1.hash
=> 3748939910403886956
> 'a'.hash
=> 1677925148165319732
> [1,2,3].hash
=> -2230614089907012012
> Time.now.hash
=> -2249667312364590389
Equal objects return the same value:
> 1 == 1
=> true
> 1.hash
=> 3748939910403886956
> 1.hash
=> 3748939910403886956
Hash comes from the Kernel
module:
> 1.method(:hash).owner
=> Kernel
The Kernel module is included by class Object, so its methods are available in every Ruby object.
It’s basically a bunch of helper methods made available to every class.
Kernel#hash
seems to be undocumented though. It’s not in in the docs for the Kernel
module. Though, that page does point towards the Object
class page for information on Kernel
instance methods. But there’s nothing on it there either.
The explanation to why #hash
needs to be overridden when #eql
is changed is in the Hash
docs.
Two objects refer to the same hash key when their hash value is identical and the two objects are eql? to each other.
Two objects can have the same hash value but be unequal however this would be detriment to the speed of the hash.
So when keying by multiple objects, so long as their hash
and eql?
values match, they will point to the same bucket.