How do I implement Swift's Comparable protocol? How do I implement Swift's Comparable protocol? swift swift

How do I implement Swift's Comparable protocol?


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  // falsepaul <= ben       // falsepaul == otherPaul // true


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)  // falseprint(paul <= ben)       // falseprint(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.