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
}
}
}
Esta pregunta ya tiene una respuesta aquí:
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