Home > front end >  Swift subclass conform to equatable called super class implemenation?
Swift subclass conform to equatable called super class implemenation?

Time:06-27

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

CodePudding user response:

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:

  • Related