Equatable y Comparable en Swift

Cuando creamos clases o estructura y queremos hacer comparaciones entre ellas no podemos simplemente usar el operador == o < ni >.

Veamos con mas detalle el siguiente ejemplo:

Definimos una clase llamada Person

class Person {  
    var id: Int
    var age: Int
    var name: String

    init(id: Int, age: Int, name: String) {
        self.id = id
        self.age = age
        self.name = name
    }
}

Creamos dos instancias de cada una y asignamos los mismo valores

let person1 = Person(id: 1, age: 56, name: "Steve")  
let person2 = Person(id: 1, age: 56, name: "Steve")

if person1 == person2 {  
    print("are equals")
} else {
    print("are differents")
}

que pasa si compilamos este codigo? imprimirá are equals?. Pues no, el compilador nos generará un error indicando que el operador == no se puede aplicar a la clase Person

Binary operator '==' cannot be applied to two 'Person' operands

Esto sucede debido a que Person es una clase que creamos y no le hemos dicho a Swift como debe hacer la comparación de este tipo de objeto.

Protocolo Equatable

Para solucionar este problema Swift proveer un protocolo llamado Equatable el cual nos obliga a implementar la función de igualdad ==.

Siguiendo el ejemplo de la clase Person solucionarlo es muy sencillo, solo debemos conformar el protocolo Equatable así:

class Person: Equatable {

    var id: Int
    var age: Int
    var name: String

    init(id: Int, age:Int, name: String) {
        self.id = id
        self.age = age
        self.name = name
    }

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

Como puedes ver la implementación de la función == es muy sencilla, solo debemos compara cada una de las propiedades de la clase.

Protocolo Comparable

El protocolo Comparable provee mas funciones y nos sirve para validar si dos objetos son mayor >, menor < e incluso si son iguales ==.
Un caso practico seria ordenar un arreglo de Person por edad. Para esto podemos usar la función sorted de los arreglos.

Lo primero que debes saber es que el protocolo Comparable conforma a Equatable, así es que podemos modificar la clase Person de la siguiente manera:

class Person: Comparable {

    var id: Int
    var age: Int
    var name: String

    init(id: Int, age: Int, name: String) {
        self.id = id
        self.age = age
        self.name = name
    }

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

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

Si te fijas, veras que lo primero que hicimos fue cambiar el protocolo Equatable por Comparable e implementar otra función requerida por este protocolo que es menor que <.

Siguiente el ejemplo vamos a crear el arreglo de objetos Person

let steve = Person(id: 1, age: 56, name: "Steve")  
let woz = Person(id: 2, age: 67, name: "Wozniak")  
let mark = Person(id: 3, age: 33, name: "Mark")  
let bill = Person(id: 4, age: 63, name: "Bill")

let people = [steve, woz, mark, bill]  

como nuestra clase Person conforma el protocolo Comprable podemos usar el operador < junto con la función sorted de los arreglos.

let peopleSorted = people.sorted {  
    return $0.age < $1.age
}

como resultado obtendremos el arreglo ordenado.

array sorted

Puedes encontrar el ejemplo completo en GitHub

Jose Aponte

Desarrollador full-stack apasionado por las tecnologías de información y los lenguajes de programación. Me gustan divertirme con mi familia, mi lema es "Nunca paras de Aprender"

Bogota

Subscribe to Jappsku Engineering Blog

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!