How Do I Implement Swift's Comparable Protocol?

How do I use the Comparable protocol in Swift? In the declaration it says I'd have to implement the three operations <, <= and >=. I put all those in the class but it doesn't work. Also do I need to have all three of them? Because it should be possible to deduce all of them from a single one.

0

3 Answers

The Comparable protocol extends the Equatable protocol -> implement both of them

In Apple's Reference is an example from Apple (within the Comparable protocol reference) you can see how you should do it: Don't put the operation implementations within the class, but rather on the outside/global scope. Also you only have to implement the < operator from Comparable protocol and == from Equatable protocol.

Correct example:

class Person : Comparable {
    let name : String

    init(name : String) {
        self.name = name
    }
}

func < (lhs: Person, rhs: Person) -> Bool {
    return lhs.name < rhs.name
}

func == (lhs: Person, rhs: Person) -> Bool {
    return lhs.name == rhs.name
}

let paul = Person(name: "Paul")
let otherPaul = Person(name: "Paul")
let ben = Person(name: "Ben")

paul > otherPaul  // false
paul <= ben       // false
paul == otherPaul // true
9

Here is an update of Kametrixom's answer for Swift 3:

class Person : Comparable {

    let name : String

    init(name : String) {
        self.name = name
    }    

    static func < (lhs: Person, rhs: Person) -> Bool {
        return lhs.name < rhs.name
    }

    static func == (lhs: Person, rhs: Person) -> Bool {
        return lhs.name == rhs.name
    }
}

Instances of the Person class can then be compared with the relational operators as follows:

let paul = Person(name: "Paul")
let otherPaul = Person(name: "Paul")
let ben = Person(name: "Ben")

print(paul > otherPaul)  // false
print(paul <= ben)       // false
print(paul == otherPaul) // true

To implement Swift's Comparable protocol, you need to conform to the Equatable protocol first by implementing static func == (lhs: Self, rhs: Self) -> Bool, then implementing the only required function static func < (lhs: Self, rhs: Self) -> Bool for Comparable.

Instead of declaring global operator overloads, you should instead implement the protocol conforming methods within the struct/class itself. Although global operator overloads satisfy the protocol conformance, it's bad practice to declare them that way instead of the intended static methods on the struct/class.

If you look at the documentation example, you will see that the same is shown as sample code.

I would instead write the following:

class Person: Comparable {
    let name: String

    init(name: String) {
        self.name = name
    }

    static func < (lhs: Person, rhs: Person) -> Bool {
        return lhs.name < rhs.name
    }

    static func == (lhs: Person, rhs: Person) -> Bool {
        return lhs.name == rhs.name
    }
}

or even separate out the protocol conformance out of the class declaration like so:

class Person {
    let name: String

    init(name: String) {
        self.name = name
    }
}

extension Person: Comparable {
    static func < (lhs: Person, rhs: Person) -> Bool {
        return lhs.name < rhs.name
    }

    static func == (lhs: Person, rhs: Person) -> Bool {
        return lhs.name == rhs.name
    }
}

which would probably be closer to production level code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

David Miller

David Miller

Executive Financial & Market Analyst

David Miller brings 15 years of experience in global economics, personal finance strategy, and market dynamics. He specializes in turning complex economic trends into actionable insights for everyday readers.

Share this article
Twitter Facebook Pinterest