Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift, how to implement Hashable protocol based on object reference?

I've started to learn swift after Java. In Java I can use any object as a key for HashSet, cause it has default hashCode and equals based on object identifier. How to achieve the same behaviour in Swift?

like image 422
Semyon Avatar asked Jan 10 '16 13:01

Semyon


People also ask

What is a hashable object Swift?

In Swift, a Hashable is a protocol that provides a hashValue to our object. The hashValue is used to compare two instances. To use the hashValue , we first have to conform (associate) the type (struct, class, etc) to Hashable property.

Can a protocol conform to hashable?

You can use any type that conforms to the Hashable protocol in a set or as a dictionary key. Many types in the standard library conform to Hashable : Strings, integers, floating-point and Boolean values, and even sets are hashable by default.

Does Nsobject conform hashable?

NSObjectProtocol doesn't inherit from Hashable .

What is the use of hashable protocol?

To conclude, a hashable protocol allows us to create custom types that can be compared for it's equality using it's hashValue . In this way we are able to use our custom type in a set or as a key in a dictionary while ensuring that it has a unique value.


2 Answers

If you are working with classes and not structs, you can use the ObjectIdentifier struct. Note that you also have to define == for your class in order to conform to Equatable (Hashable requires it). It would look something like this:

class MyClass: Hashable { }  func ==(lhs: MyClass, rhs: MyClass) -> Bool {     return ObjectIdentifier(lhs) == ObjectIdentifier(rhs) }  class MyClass: Hashable {     var hashValue: Int {         return ObjectIdentifier(self).hashValue     } } 
like image 74
Aaron Rasmussen Avatar answered Sep 19 '22 12:09

Aaron Rasmussen


In Swift, the type must conform to Hashable and Equatable for it to be used in a data structure such as a Dictionary or a Set. However, you can add "automatic conformance" by using the "object identifier" of the object. In the code below, I implemented a reusable class to do this automatically.

Note, Swift 4.2 changed how Hashable is implemented, so you no longer override hashValue. Instead, you override hash(into:).

open class HashableClass {     public init() {} }  // MARK: - <Hashable>  extension HashableClass: Hashable {      public func hash(into hasher: inout Hasher) {          hasher.combine(ObjectIdentifier(self))     }          // `hashValue` is deprecated starting Swift 4.2, but if you use      // earlier versions, then just override `hashValue`.     //     // public var hashValue: Int {     //    return ObjectIdentifier(self).hashValue     // } }  // MARK: - <Equatable>  extension HashableClass: Equatable {      public static func ==(lhs: HashableClass, rhs: HashableClass) -> Bool {         return ObjectIdentifier(lhs) == ObjectIdentifier(rhs)     } } 

To use, just take your class and subclass HashableClass, then everything should just work!

class MyClass: HashableClass {  } 
like image 32
kgaidis Avatar answered Sep 18 '22 12:09

kgaidis