title: Swift uses the wrong equality function to determine if an array contains an object
body: <p>I have a class A which conforms to Equatable and a class B which inherits from A. I defined == for each of these classes. </p>
  
  <p>When comparing two B objects, the correct == function is used to determine the equality. When checking to see whether an array of B contains an object B, the == defined for A will be called.</p>
  
  <pre><code>//: Playground - noun: a place where people can play
  
  class A: Equatable {
      var id: Int
  
      init(id: Int) {
          self.id = id
      }
  }
  
  class B: A {
  }
  
  func ==(lhs: A, rhs: A) -&gt; Bool {
      print("Comparing using A's ==")
      return false
  }
  
  
  func ==(lhs: B, rhs: B) -&gt; Bool {
      print("Comparing using B's ==")
      return lhs.id == rhs.id
  }
  
  let b1 = B(id: 1)
  let b2 = B(id: 2)
  
  let array: [B] = [b1, b2] // an array explicitly defined as containing B objects
  
  print("\((b2 == b2))")
  print("\(array.index(of: b2))")
  print("\(array.contains(b2))")
  </code></pre>
  
  <p>Output:</p>
  
  <pre><code>Comparing using B's ==
  true
  Comparing using A's ==
  Comparing using A's ==
  nil
  Comparing using A's ==
  Comparing using A's ==
  false
  </code></pre>
  
  <p>Why is this happening?</p>
  
  <p><strong>EDIT: SOLVED!</strong></p>
  
  <p>As <em>Hamish</em> commented below, this is because B will rely on A's == in certain cases, for more, see here, point #2: <a href="https://stackoverflow.com/questions/42283715/overload-for-custom-class-is-not-always-called">== overload for custom class is not always called</a></p>
  
  <p>To work around this I did the following: I defined a method called <code>isEqualTo(object:)</code> that is called from A's <code>==</code>. That method is overridden from B.</p>
  
  <p>This is probably a little bit more inefficient because of the overhead of going through another few method calls, but it works good enough for the data I am dealing with.</p>
  
  <pre><code>//: Playground - noun: a place where people can play
  
  class A: Equatable {
      var id: Int
  
      init(id: Int) {
          self.id = id
      }
  
      // define an isEqualTo method which takes another A instance
      // this will be called from A's ==
      func isEqualTo(object: A) -&gt; Bool {
          return self == object
      }
  }
  
  class B: A {
  
      // override the isEqualTo: method
      override func isEqualTo(object: A) -&gt; Bool {
  
          // if we are actually dealing with an object of type B, cast it 
          // first, then call B's ==
          if let bObject = object as? B {
              return self == bObject
          }
  
          // fallback to A's  ==
          return super.isEqualTo(object: object)
      }
  }
  
  func ==(lhs: A, rhs: A) -&gt; Bool {
      print("Comparing using A's ==")
      // use a designated, overridable method to determine equality
      return lhs.isEqualTo(object: rhs)
  }
  
  
  func ==(lhs: B, rhs: B) -&gt; Bool {
      print("Comparing using B's ==")
      return lhs.id == rhs.id
  }
  
  let b1 = B(id: 1)
  let b2 = B(id: 2)
  
  let array: [B] = [b1, b2]
  
  print("\((b2 == b2))")
  print("\(array.index(of: b2))")
  print("\(array.contains(b2))")
  </code></pre>
  
  <p>Output:</p>
  
  <pre><code>Comparing using B's ==
  true
  Comparing using A's ==
  Comparing using B's ==
  Comparing using A's ==
  Comparing using B's ==
  Optional(1)
  Comparing using A's ==
  Comparing using B's ==
  Comparing using A's ==
  Comparing using B's ==
  true
  </code></pre>