Langue: Swift2.3
Par exemple, je vais vous montrer différents types d'énums
enum Normal {
case one
case two, three
}
enum NormalRaw: Int {
case one
case two, three
}
enum NormalArg {
case one(Int)
case two, three
}
Switch
peut être utilisé sur les trois énumérations comme suit:
var normal: Normal = .one
var normalRaw: NormalRaw = .one
var normalArg: NormalArg = .one(1)
switch normal {
case .one: print("1")
default: break
}
switch normalRaw {
case .one: print(normalRaw.rawValue)
default: break
}
switch normalArg {
case .one(let value): print(value)
default: break
}
Sur l'instruction if-else, je ne peux faire que des comparaisons pour Normal
et NormalRaw
, et un message d'erreur s'affiche pour NormalArg
. Je ne peux donc pas exécuter le code.
L'opérateur binaire '==' ne peut pas être appliqué aux opérandes de type
NormalArg
et_
Voici l'exemple de code:
if normal == .two { // no issue
.. do something
}
if normalRaw == .two { // no issue
.. do something
}
if normalArg == .two { // error here (the above message)
.. do something
}
if normalArg == .one(_) { // error here (the above message)
.. do something
}
if normalArg == .three { // error here (the above message)
.. do something
}
Des idées? Je ne fais vraiment rien avec ce code, je me demande simplement pourquoi nous ne pouvons pas faire de comparaison.
L'astuce consiste à ne pas vérifier avec ==, mais plutôt à utiliser le mot clé case
conjointement avec un seul = dans votre instruction if. C'est un peu contre-intuitif au début mais comme if let
, tu t'y habitues assez vite:
enum Normal {
case one
case two, three
}
enum NormalRaw: Int {
case one = 1
case two, three
}
enum NormalArg {
case one(Int)
case two, three
}
let normalOne = Normal.one
let normalRawOne = NormalRaw.one
let normalArgOne = NormalArg.one(1)
if case .one = normalOne {
print("A normal one") //prints "A normal one"
}
if case .one = normalRawOne {
print("A normal \(normalRawOne.rawValue)") //prints "A normal 1"
}
if case .one(let value) = normalArgOne {
print("A normal \(value)") //prints "A normal 1"
}
Le fait est que dans Swift vous obtenez uniquement l’équation des enums gratuitement si votre enum utilise un type brut ou si vous n’avez aucune valeur associée (essayez-la, vous ne pouvez pas avoir les deux en même temps). même temps). Swift mais ne sait pas comment comparer les cas avec des valeurs associées - je veux dire comment cela pourrait-il? Voyons cet exemple:
Normal.one == .one //true
Normal.one == .two //false
NormalRaw.one == .one //true
NormalRaw.one == .two //false
NormalArg.one(1) == .one(1) //Well...?
NormalArg.one(2) == .one(1) //Well...?
NormalArg.one(1) == .two //Well...?
Cela explique peut-être pourquoi cela ne fonctionne pas:
class Special {
var name: String?
var special: Special?
}
enum SpecialEnum {
case one(Special)
case two
}
var special1 = Special()
special1.name = "Hello"
var special2 = Special()
special2.name = "World"
special2.special = special1
SpecialEnum.one(special1) == SpecialEnum.one(special2) //Well...?
Donc, si vous voulez des énumérations avec des valeurs associées, vous devrez implémenter vous-même le protocole Equatable:
enum NormalArg: Equatable {
case one(Int)
case two
static func ==(lhs: NormalArg, rhs: NormalArg) -> Bool {
switch (lhs, rhs) {
case (let .one(a1), let .one(a2)):
return a1 == a2
case (.two,.two):
return true
default:
return false
}
}
}
La réponse est Protocole Équitable.
Voyons maintenant comment cela fonctionne.
Considérez cet enum par exemple:
enum Barcode {
case upca(Int, Int)
case qrCode(String)
case none
}
Si on vérifie l'opérateur d'équilibre ==
sur l'énumération, elle échouera.
// Error: binary operator '==' cannot be applied to two Barcode operands
Barcode.qrCode("code") == Barcode.qrCode("code")
Comment résoudre ce problème en utilisant Equatable Protocol?
extension Barcode: Equatable {
}
func ==(lhs: Barcode, rhs: Barcode) -> Bool {
switch (lhs, rhs) {
case (let .upca(codeA1, codeB1), let .upca(codeA2, codeB2)):
return codeA1 == codeA2 && codeB1 == codeB2
case (let .qrCode(code1), let .qrCode(code2)):
return code1 == code2
case (.None, .None):
return true
default:
return false
}
}
Barcode.qrCode("code") == Barcode.qrCode("code") // true
Barcode.upca(1234, 1234) == Barcode.upca(4567, 7890) // false
Barcode.none == Barcode.none // true