Si vous mettre directement en œuvre l' Equatable
sur un protocole, il ne sera pas plus être utilisable comme un type, qui va à l'encontre de l'objectif de l'utilisation d'un protocole. Même si vous venez de mettre en oeuvre ==
fonctions sur les protocoles sans Equatable
de conformité, les résultats peuvent être erronés. Voir ce post sur mon blog pour une démonstration de ces questions:
https://khawerkhaliq.com/blog/swift-protocols-equatable-part-one/
La solution que j'ai trouvé le mieux est d'utiliser le type de l'effacement. Cela permet de formuler ==
comparaisons pour les types de protocole (enveloppé dans le type de gommes à effacer). Il est important de noter que, tandis que nous continuons à travailler au niveau du protocole, le réel ==
comparaisons sont délégués de la sous-types de béton pour garantir des résultats corrects.
J'ai construit un type de gomme à l'aide de votre exemple et ajouté un peu de code de test à la fin. J'ai ajouté une constante de type String
pour le protocole et a créé deux conformes types (les structures sont les plus faciles pour fins de démonstration) pour être en mesure de tester les différents scénarios.
Pour une explication détaillée du type d'effacement de la méthodologie utilisée, vérifiez la partie deux de ce qui précède post de blog:
https://khawerkhaliq.com/blog/swift-protocols-equatable-part-two/
Le code ci-dessous devrait soutenir la comparaison d'égalité que vous avez voulu mettre en œuvre. Vous avez juste à envelopper le type de protocole dans un type de gomme à l'instance.
protocol X {
var name: String { get }
func isEqualTo(_ other: X) -> Bool
func asEquatable() -> AnyEquatableX
}
extension X where Self: Equatable {
func isEqualTo(_ other: X) -> Bool {
guard let otherX = other as? Self else { return false }
return self == otherX
}
func asEquatable() -> AnyEquatableX {
return AnyEquatableX(self)
}
}
struct Y: X, Equatable {
let name: String
static func ==(lhs: Y, rhs: Y) -> Bool {
return lhs.name == rhs.name
}
}
struct Z: X, Equatable {
let name: String
static func ==(lhs: Z, rhs: Z) -> Bool {
return lhs.name == rhs.name
}
}
struct AnyEquatableX: X, Equatable {
var name: String { return value.name }
init(_ value: X) { self.value = value }
private let value: X
static func ==(lhs: AnyEquatableX, rhs: AnyEquatableX) -> Bool {
return lhs.value.isEqualTo(rhs.value)
}
}
// instances typed as the protocol
let y: X = Y(name: "My name")
let z: X = Z(name: "My name")
let equalY: X = Y(name: "My name")
let unequalY: X = Y(name: "Your name")
// equality tests
print(y.asEquatable() == z.asEquatable()) // prints false
print(y.asEquatable() == equalY.asEquatable()) // prints true
print(y.asEquatable() == unequalY.asEquatable()) // prints false
A noter que depuis le type de gomme est conforme au protocole, vous pouvez utiliser des instances du type gomme n'importe où une instance du type de protocole est prévu.
Espérons que cette aide.