I think I did a mistake and didn't want to write "the object" but "an NSObject", but the main point didn't change much: an object is always a reference type, but can have value semantics. e.g.
final class MyReference {
let identifier: Int
let name: String
init(...) { ... }
}
This object has value semantics, and it's substitutable with any other instance with the same identifier and name values. There is a point to be made that this type should really be a struct, but I think there is a separate discussion to be made on this.
I disagree that this conformance to Equatable is correct. It's certainly doable, but unless these "other states" are only metadata and not relevant to how the object is used, then it breaks the semantic requirements of the protocol.
From the Equatable docs:
Equality implies substitutability—any two instances that compare equally can be used interchangeably in any code that depends on their values. To maintain substitutability, the
==operator should take into account all visible aspects of anEquatabletype. Exposing nonvalue aspects ofEquatabletypes other than class identity is discouraged, and any that are exposed should be explicitly pointed out in documentation.
and
Equality is Separate From Identity
The identity of a class instance is not part of an instance’s value. Consider a class called
IntegerRefthat wraps an integer value. Here’s the definition forIntegerRefand the==function that makes it conform toEquatable:class IntegerRef: Equatable { let value: Int init(_ value: Int) { self.value = value } static func == (lhs: IntegerRef, rhs: IntegerRef) -> Bool { return lhs.value == rhs.value } }The implementation of the
==function returns the same value whether its two arguments are the same instance or are two different instances with the same integer stored in their value properties. For example:let a = IntegerRef(100) let b = IntegerRef(100) print(a == a, a == b, separator: ", ") // Prints "true, true"Class instance identity, on the other hand, is compared using the triple-equals identical-to operator (
===). For example:let c = a print(c === a, c === b, separator: ", ") // Prints "true, false"