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.