34

The Hashable protocol in Swift requires you to implement a property called hashValue:

protocol Hashable : Equatable {
    /// Returns the hash value.  The hash value is not guaranteed to be stable
    /// across different invocations of the same program.  Do not persist the hash
    /// value across program runs.
    ///
    /// The value of `hashValue` property must be consistent with the equality
    /// comparison: if two values compare equal, they must have equal hash
    /// values.
    var hashValue: Int { get }
}

However, it seems there's also a similar property called hash.

What is the difference between hash and hashValue?

jscs
  • 63,694
  • 13
  • 151
  • 195
cfischer
  • 24,452
  • 37
  • 131
  • 214
  • 3
    `hash` is a property of the [`NSObject` protocol](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Protocols/NSObject_Protocol/), compare [NSObject subclass in Swift: hash vs hashValue, isEqual vs ==](http://stackoverflow.com/questions/33319959/nsobject-subclass-in-swift-hash-vs-hashvalue-isequal-vs). – Martin R Aug 14 '16 at 21:17

1 Answers1

40

hash is a required property in the NSObject protocol, which groups methods that are fundamental to all Objective-C objects, so that predates Swift. The default implementation just returns the objects address, as one can see in NSObject.mm, but one can override the property in NSObject subclasses.

hashValue is a required property of the Swift Hashable protocol.

Both are connected via a NSObject extension defined in the Swift standard library in ObjectiveC.swift:

extension NSObject : Equatable, Hashable {
  /// The hash value.
  ///
  /// **Axiom:** `x == y` implies `x.hashValue == y.hashValue`
  ///
  /// - Note: the hash value is not guaranteed to be stable across
  ///   different invocations of the same program.  Do not persist the
  ///   hash value across program runs.
  open var hashValue: Int {
    return hash
  }
}

public func == (lhs: NSObject, rhs: NSObject) -> Bool {
  return lhs.isEqual(rhs)
}

(For the meaning of open var, see What is the 'open' keyword in Swift?.)

So NSObject (and all subclasses) conform to the Hashable protocol, and the default hashValue implementation return the hash property of the object.

A similar relationship exists between the isEqual method of the NSObject protocol, and the == operator from the Equatable protocol: NSObject (and all subclasses) conform to the Equatable protocol, and the default == implementation calls the isEqual: method on the operands.

Community
  • 1
  • 1
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • "Do not persist the hash value across program runs." ... would have been useful to know lol ... just wasted 2 hours wondering why my persisted hashes were not the same – quemeful Jan 18 '19 at 16:18
  • 1
    @quemeful: It was always *documented* as non-persistent, but only as of Swift 4.2 this is actively enforced in the Swift library by using a per-execution random seed, compare https://github.com/apple/swift-evolution/blob/master/proposals/0206-hashable-enhancements.md#the-hasher-struct . – Martin R Jan 18 '19 at 17:55
  • It appears `hash` is persistent (at least used from objective c) and `hashValue` isn't. – Declan McKenna Oct 19 '20 at 07:41
  • 2
    @DeclanMcKenna: `hashValue` and `hash` should return the same value for `NSObject` subclasses (the memory address) unless overridden in a subclass. That memory address *can* be the same across multiple runs of the program, but you can not rely on it. – Martin R Oct 20 '20 at 12:15