type the switch raw not have generic extension enum does cannot swift enums

swift - the - Cómo hacer una comparación if-else en enumeraciones con argumentos



swift generic enum (2)

El truco es no verificar realmente con == sino usar la palabra clave del case junto con un solo = en su declaración if. Este es un pequeño contador intuitivo al principio, pero como if let , te acostumbras bastante rápido:

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" }

El punto es que en Swift solo obtienes la ecuación de enumeraciones gratis si tu enumeración usa un tipo en bruto o si no tienes valores asociados (pruébalo, no puedes tener ambos al mismo tiempo). Sin embargo, Swift no sabe cómo comparar los casos con valores asociados. Quiero decir, ¿cómo podría hacerlo? Veamos este ejemplo:

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...?

Tal vez esto aclara por qué esto no puede funcionar fuera de la caja:

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...?

Por lo tanto, si desea enumeraciones con valores asociados, deberá implementar el protocolo Equatable en su enumeración:

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 } } }

Idioma : Swift2.3

Por ejemplo, vamos a mostrarte diferentes tipos de enumeraciones

enum Normal { case one case two, three } enum NormalRaw: Int { case one case two, three } enum NormalArg { case one(Int) case two, three }

Switch se puede usar en las tres enumeraciones así:

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 }

En la sentencia if-else, aunque solo puedo hacer una comparación para Normal y NormalRaw , y aparece un mensaje de error para NormalArg , así que no puedo ejecutar el código

El operador binario ''=='' no se puede aplicar a operandos de tipo NormalArg y _

Aquí está el ejemplo del código:

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 }

¿Algunas ideas? Realmente no estoy haciendo nada con este código, solo me pregunto por qué no podemos hacer una comparación.


La respuesta es Equatable Protocol .

Ahora veamos cómo funciona.

Considere esta enumeración por ejemplo:

enum Barcode { case upca(Int, Int) case qrCode(String) case none }

Si verificamos el operador equatable == en la enumeración, fallará.

// Error: binary operator ''=='' cannot be applied to two Barcode operands Barcode.qrCode("code") == Barcode.qrCode("code")

¿Cómo arreglar esto usando el Protocolo Equatable?

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