Hashable Protocol in Swift
What is Hashable Protocol?
It’s defined in Apple’s documentation as “a type that provides an integer hash value”. A hashValue
is an integer that is the same for any two instances that compare equally.
The Hashable protocol is faster, simpler, and more secure.
What is a hash value?
A hash value is a number generated from a string of text. The hash is smaller than the text itself.
It is used for encryption and authentication, but it is also applied to data structures. It’s called a hash table, and Swift uses it to represent a dictionary.
Swift 4.1 or earlierHashablable
Let’s look at the following example:
Only types that conform to the Hashable
protocol that used as values in a Set
, or keys inDictionary
. In order to fix these errors, custom type Fruit
need to adopt Hashable
protocol.
What do you mean if type conforms to Hashable
protocol?
There are two things which we have to consider
- Conform to the
Equatable
protocol - Implement a
hashValue
for your type
conforming to the Hashable protocol was irritating. I needed to implement var hashValue: Int { get }
Hashable compliance and I had to build my own logic to return the hash value. In Swift 4.1, hashValue is now implicitly implemented by conforming to Hashable.
What are Hash collisions?
- Although
hashValue
is implemented implicitly, if you implement it yourself you calculate the hash value with your own algorithm, it can become a vulnerability in itself. Hash collisions can occur, and bad algorithms can slow performance. - We have two instances
a
andb
of the same type, ifa == b
, thena.hashValue == b.hashValue
. However, the reverse is not always true: two instances with equal hash values are not necessarily equal to each other. This is known as a hash collision.
How to overcome a hash collision?
When hash collisions occur, objects with matching hashes are checked for equality. This is the reason Hashable
inherits from the Equatable
protocol, any type that conforms to Hashable
must also conform to Equatable
.
So far we have only covered hashValue
property, but since Hashable protocol also conforms with Equatable (protocol indicating that it is comparable), ==(_:_)
it needs to be implemented, but this is also implicitly implemented after Swift 4.1. You can read the Equatable
protocol I have already covered in Equatable
protocol article
Staring with Swift 4.2 Hashablable
hashValue
is deprecated. So If you conform to Hashable
protocol, we need to implement the hash(into:)
function. With this implementation, you can leave the hash value generation algorithm to Swift. To avoid Hash collisions and slow performance.
How is Hasher generating hash value?
Hasher can also be used as a hash value generator.
Hasher stores the state of the hash function and uses the combine
method to pass the new data to the hash function and mix it with the state it is capturing.
Then finalize the state with thefinalizer()
method and extract the hash value. Hasher generates a hash value in this way
Since enum seems to implement Hashable and Equalable by default, it can be specified as a dictionary key.