El protocolo Swift implementa Equatable
swift2 protocols (2)
1) Permita que se Cacheable
dos Cacheable
s del mismo tipo
protocol Cacheable: Equatable {
//....//
func identifier() -> String
}
func ==<T : Cacheable>(lhs: T, rhs: T) -> Bool {
return lhs.identifier() == rhs.identifier()
}
Pros
Esta es la solución más simple.
Contras
Solo puede comparar dos objetos Cacheable
del mismo tipo. Esto significa que el código a continuación fallará y para corregirlo debe hacer que Animal
ajuste a Cacheable
:
class Animal {
}
class Dog: Animal,Cacheable {
func identifier() -> String {
return "object"
}
}
class Cat: Animal,Cacheable {
func identifier() -> String {
return "object"
}
}
let a = Dog()
let b = Cat()
a == b //such comparison is not allowed
2) Permitir que se Cacheable
las Cacheable
de cualquier tipo
protocol Cacheable:Equatable {
//....//
func identifier() -> String
}
func ==<T:Cacheable>(lhs: T, rhs: T) -> Bool {
return lhs.identifier() == rhs.identifier()
}
func !=<T:Cacheable>(lhs: T, rhs: T) -> Bool {
return lhs.identifier() != rhs.identifier()
}
func ==<T:Cacheable, U:Cacheable>(lhs: T, rhs: U) -> Bool {
return lhs.identifier() == rhs.identifier()
}
func !=<T:Cacheable, U:Cacheable>(lhs: T, rhs: U) -> Bool {
return lhs.identifier() != rhs.identifier()
}
Pros
Elimina las limitaciones descritas anteriormente para la solución 1. Ahora puede comparar fácilmente el Dog
y el Cat
.
Contras
- La implementación es más larga. En realidad, no estoy seguro de por qué especificar solo funciones
==
no es suficiente, esto podría ser un error con un compilador. De todos modos, debe proporcionar la implementación tanto para==
como para!=
. - En algunos casos, el beneficio de esta implementación también puede plantear un problema ya que permite la comparación entre objetos absolutamente diferentes y el compilador está totalmente de acuerdo.
3) Sin conformidad con Equatable
protocol Cacheable {
//....//
func identifier() -> String
}
func ==(lhs: Cacheable, rhs: Cacheable) -> Bool {
return lhs.identifier() == rhs.identifier()
}
func !=(lhs: Cacheable, rhs: Cacheable) -> Bool {
return lhs.identifier() != rhs.identifier()
}
Pros
Puede usar Cacheable
como tipo sin necesidad de genéricos. Esto introduce una nueva gama de posibilidades. Por ejemplo:
let c:[Cacheable] = [Dog(),RaceCar()]
c[0] == c[1]
c[0] != c[1]
Con las soluciones 1 y 2, dicho código fallaría y tendría que usar genéricos en sus clases. Sin embargo, con la última implementación Cacheable
se trata como un tipo, por lo que se le permite declarar una matriz de tipo [Cacheable]
.
Contras
Ya no declaras la conformidad con Equatable
por lo que cualquier función que acepte parámetros Equatable
no aceptará Cacheable
. Obviamente, aparte de ==
y !=
Como los Cacheable
para Cacheable
s.
Si esto no es un problema en tu código, preferiría esta solución. Ser capaz de tratar el protocolo como un tipo es muy útil en muchos casos.
Tengo el siguiente Protocol
:
protocol Cacheable {
//....//
func identifier() -> String
}
¿Puedo hacer que Cacheable
implemente Equatable?
cuando hago lo siguiente:
extension Cacheable: Equatable {}
func ==(lhs:Cacheable,rhs:Cacheable) -> Bool {
return lhs.identifier() == rhs.identifier()
}
Recibí este mensaje de error: Extensión del protocolo Cacheable
no puede tener una cláusula de herencia
Tratar.
extension Equatable where Self : Cacheable {
}