Implement Equatable protocol in a class hierarchy

Having tried it in various languages over the years, the recipe I follow goes like this:

  • Static == function on the base class that calls a normal instance method, usually called equals(_ other: BaseClass)
  • Each subclass implements equals in a sensible way per its own implementation but the rule is that the other object must have exactly the same type as self in order to compare equal.

So your class A would have

static func == (a: A, b: A) -> Bool { return a.equals(b) }

func equals(other: A) -> Bool 
{
    guard type(of: other) == type(of: self) else { return false }
    return self.a == other.a
}

And B would have:

func equals(other: A) -> Bool 
{
    guard let otherAsB = other as? B else { return false }
    return self.a == otherAsB.a && self.b == otherAsB.b
}

This is the only way I have found to guarantee symmetry (i.e. a == b implies b == a) and transitivity (a == b && b == c implies a == c).

2 Likes