Enums con superpoderes
Los enums de Swift no son simples constantes: llevan valores asociados, métodos y encajan con el pattern matching de switch para modelar estados con precisión.
Los enums de Swift están entre los más potentes de cualquier lenguaje. Van mucho más allá de una lista de opciones: modelan estados, transportan datos y, combinados con switch, hacen imposible olvidar un caso. Son una herramienta de diseño, no un detalle.
- Enums básicos y raw values.
- Valores asociados: enums que llevan datos.
- Pattern matching exhaustivo con switch.
- Métodos y CaseIterable.
Enum básico
Un conjunto cerrado de casos posibles:
enum Direccion {
case norte, sur, este, oeste
}
let rumbo = Direccion.norte
Raw values
Cada caso puede tener un valor “crudo” asociado de forma fija (String, Int…):
enum Planeta: Int {
case mercurio = 1, venus, tierra, marte // 1, 2, 3, 4 automáticos
}
print(Planeta.tierra.rawValue) // 3
let p = Planeta(rawValue: 4) // Planeta? (opcional: podría no existir)
Valores asociados: la joya
Cada caso puede llevar datos distintos. Esto convierte al enum en una forma de modelar estados con su información:
enum Resultado {
case exito(datos: String)
case error(codigo: Int, mensaje: String)
case cargando
}
let r = Resultado.error(codigo: 404, mensaje: "No encontrado")
Piensa en un estado de carga con isLoading, data y error como tres variables sueltas: podrías tener isLoading = true y un error a la vez, un estado imposible que igualmente compila. Con un enum de valores asociados, cada estado es exclusivo por diseño: o estás cargando, o tienes exito(datos), o error(...), nunca dos a la vez. Haces que los estados inválidos sean irrepresentables. Es una de las técnicas de modelado más poderosas de Swift.
switch: pattern matching exhaustivo
El switch sobre un enum te obliga a cubrir todos los casos, y extrae los valores asociados:
switch r {
case .exito(let datos):
print("OK: \(datos)")
case .error(let codigo, let mensaje):
print("Error \(codigo): \(mensaje)")
case .cargando:
print("Cargando…")
}
Si mañana añades un caso nuevo al enum (case timeout), todos los switch que no lo manejen dejarán de compilar hasta que lo cubras. El compilador te lleva de la mano a cada sitio que hay que actualizar. Olvidar un caso deja de ser posible.
Métodos en enums
Los enums pueden tener métodos y propiedades computadas:
enum Semaforo {
case rojo, amarillo, verde
var siguiente: Semaforo {
switch self {
case .rojo: .verde
case .verde: .amarillo
case .amarillo: .rojo
}
}
}
print(Semaforo.rojo.siguiente) // verde
CaseIterable
Añade CaseIterable y obtienes una colección con todos los casos, ideal para menús y pickers:
enum Tema: String, CaseIterable {
case claro, oscuro, sistema
}
for tema in Tema.allCases {
print(tema.rawValue) // claro, oscuro, sistema
}
- Crea un enum
EstadoPedidocon casospendiente,enviado(tracking: String)yentregado. - Escribe un
switchque imprima un mensaje distinto por caso, extrayendo el tracking. - Añade una propiedad computada
esFinalque devuelva true solo paraentregado. - Haz un enum
CaseIterabley recorreallCases.