2
class Base: Equatable {
    static func == (lhs: Base, rhs: Base) -> Bool {
        lhs.id == rhs.id
    }
    let id: String
    init(id: String) {
        self.id = id
    }
}

class SubClass: Base {
    public var id2: String?
    public init(id1: String, id2: String? = nil) {
        self.id2 = id2
        super.init(id: id1)
    }
    static func == (lhs: SubClass, rhs: SubClass) -> Bool {
        lhs.id2 == rhs.id2 && lhs.id == rhs.id
    }
}
print(a != b) // result: false
// Calls `Base` class's static func ==
print(a == b) // result: false
// Calls `SubClass` class's static func ==

I have a simple super class and subclass, subclass inherits Base and also implements static func ==

When calling a != b, it calls Base class's == implementation instead of SubClass's == implementation, why? But when calling a == b, it actually call's SubClass's == implementation, why?

I expect both != and == calls SubClass's == implementation

Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116
Johnny
  • 2,589
  • 2
  • 27
  • 34

1 Answers1

0

This problem existed long time ago since the improvement of Swift language (https://github.com/apple/swift-evolution/blob/master/proposals/0091-improving-operators-in-protocols.md)

And the author also mentioned about this problem. You can check that. https://github.com/apple/swift-evolution/blob/master/proposals/0091-improving-operators-in-protocols.md#class-types-and-inheritance

One of the solution I found is define an isEqual function.

class Superclass: Equatable {
    var foo: Int

    init(foo: Int) {
        self.foo = foo
    }

    func isEqual(to instance: Superclass) -> Bool {
        return self.foo == instance.foo
    }

    static func ==(lhs: Superclass, rhs: Superclass) -> Bool {
        return type(of: lhs) == type(of: rhs) && lhs.isEqual(to: rhs)
    }
}

class Subclass: Superclass {
    var bar: String

    init(foo: Int, bar: String) {
        self.bar = bar
        super.init(foo: foo)
    }

    override func isEqual(to instance: Superclass) -> Bool {
        guard let instance = instance as? Subclass else {
            return false
        }
        return self.foo == instance.foo && self.bar == instance.bar
    }
}

let a = Subclass(foo: 1, bar: "a")
let b = Subclass(foo: 1, bar: "b")

print(a == b) // False
print(a != b) // True

Reference:

Phuc
  • 66
  • 1
  • 4