Comment rendre une structure conforme au protocole "Equatable"?
J'utilise Xcode 7.3.1
struct MyStruct {
var id: Int
var value: String
init(id: Int, value: String) {
self.id = id
self.value = value
}
var description: String {
return "blablabla"
}
}
Lorsque j'utilise "MyStruct", Xcode affiche l'erreur:
MyStruct n'est pas conforme au protocole "Equatable"
Vous avez une idée pour rendre MyStruct conforme au protocole?
OK, après beaucoup de recherches, ça marche ...
struct MyStruct {
var id: Int
var value: String
init(id: Int, value: String) {
self.id = id
self.value = value
}
var description: String {
return "blablabla"
}
}
extension MyStruct: Equatable {}
func ==(lhs: MyStruct, rhs: MyStruct) -> Bool {
let areEqual = lhs.id == rhs.id &&
lhs.value == rhs.value
return areEqual
}
Mon Struct était dans une classe, donc ça n'a pas fonctionné .. J'ai retiré ce Struct de ma classe et maintenant c'est bon :)
À partir de Swift 4.1, tout ce que vous avez à faire est de vous conformer au protocole Equatable
sans avoir à implémenter le ==
méthode. Voir: SE-0185 - Synthèse de conformité équitable et hashable .
Exemple:
struct MyStruct: Equatable {
var id: Int
var value: String
}
let obj1 = MyStruct(id: 101, value: "object")
let obj2 = MyStruct(id: 101, value: "object")
obj1 == obj2 // true
Gardez à l'esprit que le comportement par défaut du ==
est de comparer tout les propriétés du type (basé sur l'exemple: lhs.id == rhs.id && lhs.value == rhs.value
). Si vous visez à obtenir un comportement personnalisé (en comparant une seule propriété par exemple), vous devez le faire vous-même:
struct MyStruct: Equatable {
var id: Int
var value: String
}
extension MyStruct {
static func ==(lhs: MyStruct, rhs: MyStruct) -> Bool {
return lhs.id == rhs.id
}
}
let obj1 = MyStruct(id: 101, value: "obj1")
let obj2 = MyStruct(id: 101, value: "obj2")
obj1 == obj2 // true
À ce stade, l'égalité serait basée sur la valeur id
, quelle que soit la valeur de value
.
Le problème n'est pas que la structure se trouve dans une classe. C'est certainement permis, et il y a de nombreux cas où vous voudrez peut-être le faire. Le problème réside dans la mise en œuvre du protocole Equatable. Vous devez donner une implémentation globale de == (ce que vous avez fait), mais il n'y a pas d'entité MyStruct .... c'est ParentClass.MyStruct (si la structure est définie dans une classe parent). L'exemple ci-dessous en soi n'est probablement pas un bon exemple dans ce cas, mais il montre comment vous pouvez le faire si nécessaire.
class ParentClass {
struct MyStruct {
var id: Int
var value: String
init(id: Int, value: String) {
self.id = id
self.value = value
}
var description: String {
return "blablabla"
}
}
}
extension ParentClass.MyStruct: Equatable {}
func ==(lhs: ParentClass.MyStruct, rhs: ParentClass.MyStruct) -> Bool {
let areEqual = lhs.id == rhs.id &&
lhs.value == rhs.value
return areEqual
}
let s1 = ParentClass.MyStruct(id: 1, value: "one")
let s2 = ParentClass.MyStruct(id: 2, value: "two")
let s3 = ParentClass.MyStruct(id: 1, value: "one")
s1.description //blablabla
s1 == s2 //false
s3 == s1 //true
Remarque: j'aime implémenter Comparable plutôt qu'Equatable, ce qui vous permettra de prendre en charge le tri et d'autres fonctionnalités.