How to properly implement the Equatable protocol in a class hierarchy?

Following the other answers I came up with this:

class Base : Equatable {
    var x : Int
    static func == (lhs: Base, rhs: Base) -> Bool {
        return lhs.x == rhs.x
    }
}

class Subclass : Base {
    var y : String
    static func == (lhs: Subclass, rhs: Subclass) -> Bool {
        return lhs.y == rhs.y && (lhs as Base) == (rhs as Base)
    }
}

After lots of research and some trial and error I finally came up with a working solution. The first step was moving the == operator from inside the class to the global scope. This fixed the errors about static and final.

For the base class this became:

func == (lhs: Base, rhs: Base) -> Bool {
    return lhs.x == rhs.x
}

class Base : Equatable {
    var x : Int
}

And for the subclass:

func == (lhs: Subclass, rhs: Subclass) -> Bool {
    return true
}

class Subclass : Base {
    var y : String
}

Now the only part left is figuring out how to call the == operator of the base class from the == operator of the subclass. This led me to the final solution:

func == (lhs: Subclass, rhs: Subclass) -> Bool {
    if lhs.y == rhs.y {
        if lhs as Base == rhs as Base {
            return true
        }
    }

    return false
}

That first if statement results in a call to the == operator in the base class.


The final solution:

Base.swift:

func == (lhs: Base, rhs: Base) -> Bool {
    return lhs.x == rhs.x
}

class Base : Equatable {
    var x : Int
}

Subclass.swift:

func == (lhs: Subclass, rhs: Subclass) -> Bool {
    if lhs.y == rhs.y {
        if lhs as Base == rhs as Base {
            return true
        }
    }

    return false
}

class Subclass : Base {
    var y : String
}