Swift – Enumeraciones

Definición

Las enumeraciones son un tipo de dato que permiten definir un grupo de valores relacionados bajo un nombre. Cada uno de estos valores dentro de la enumeración son llamados miembros o casos y poseen a su vez, un nombre que los identifica. Esto es, al definir una enumeración, se establecen los posibles estados que ese enum puede llegar a valer. Todos esos estados, o miembros, están relacionados entre sí.

Por ejemplo, si quisiera crear una variable sobre los puntos cardinales sabemos que, en principio, tiene cuatro posibles valores: Norte, Sur, Este y Oeste. Esos cuatro valores podrían ser miembros de un enum llamado PuntosCardinales y la variable a crear podría tomar uno de esos estados.

Sintaxis de las enumeraciones en Swift

Para definir una enumeración se utiliza la palabra reservada enum seguida del nombre de la misma.

Luego, el cuerpo de la enumeración se encierra entre llaves, como vemos a continuación:

enum Enumeracion {
    //Cuerpo de la enumeración
}

Para definir los miembros de una enumeración, se utiliza la palabra reservada case. Siguiendo el ejemplo de los puntos cardinales, su estructura sería la siguiente:

enum PuntoCardinal {
    case norte
    case sur
    case este
    case oeste
}

A su vez, cada caso puede definirse en una sola línea, usando una sola vez la palabra case y separando cada miembro por comas:

enum PuntoCardinal {
    case norte, sur, este, oeste
}

Convención de nombres para las enumeraciones en Swift

Al igual que las clases y las estructuras, las enumeraciones también son tipos de datos que creamos en nuestro código. Por lo tanto, el nombre que le asignemos debe comenzar con una mayúscula y, en caso de ser varias palabras, cada una de ellas debe separarse por mayúsculas sin usar guiones bajos u otro símbolo (camel case).

Otro punto a considerar es que el nombre de la enumeración debe estar en singular y nunca en plural. Esto es así ya que las enumeraciones se usan dentro de variables o constantes, por lo tanto solo pueden adoptar 1 valor a la vez. Siguiendo el caso anterior, si creamos una variable para el punto cardinal tendríamos lo siguiente:

var direccion = PuntoCardinal.norte

La lectura de la asignación anterior es muy clara. Se está eligiendo un punto cardinal de un listado de posibles valores y dicho valor se está guardando en la variable dirección.

Uso de las enumeraciones en Swift

Como vimos, tanto las variables como las constantes pueden ser del tipo de una enumeración. En su asignación inicial, debemos especificar el nombre del enum que vamos a usar y el valor que va a tomar dentro de la enumeración.

Supongamos que tenemos la siguiente enumeración:

enum DiaDeLaSemana {
    case lunes, martes, miercoles, jueves, viernes, sabado, domingo
}

Una posible asignación a una variable podría ser la siguiente:

var mañana = DiaDeLaSemana.martes

Como la variable mañana se inicia por primera vez, debemos especificar que su valor va a ser alguno de los contenidos dentro de la enumeración DiaDeLaSemana. Sin embargo, si quisiéramos modificar su valor, ya no es necesario volver a indicar el tipo de dato:

mañana = .miercoles

Como ya sabemos que mañana es un DiaDeLaSemana, directamente podemos asignarle otro valor dentro del enum usando un punto y el nuevo valor.

Comparar valores de las enumeraciones en Swift

Durante nuestro código, una vez que tengamos una variable con un cierto valor de los disponibles de una enumeración, vamos a necesitar preguntar por él para tomar una decisión.

Comparar con if

Podemos usar if para conocer el valor de la variable:

if mañana == DiaDeLaSemana.lunes {
print(«Se termina el fin de semana!»)
}

Asimismo, tal como vimos antes, podemos simplificar el código anterior sin mencionar el tipo de dato:

if mañana == .lunes {
    print("Se termina el fin de semana!")
}

Comparar con switch

Sin embargo, si tenemos una enumeración con varios casos y deseamos codificar un comportamiento para cada uno, usar un if no va a ser la mejor opción. En esos casos, conviene usar switch:

switch mañana {
    case .lunes:
        print("Mañana es lunes")
    case .martes:
        print("Mañana es martes")
    case .miercoles:
        print("Mañana es miércoles")
    case .jueves:
        print("Mañana es jueves")
    case .viernes:
        print("Mañana es viernes")
    case .sabado:
        print("Mañana es sábado")
    case .domingo:
        print("Mañana es domingo")
}
//Devuelve
//Mañana es miércoles

Cómo comentamos en el capítulo de control de flujo, la sentencia Switch necesita que los casos sean exhaustivos, es decir, que se contemplen todos los posibles valores que esa variable pueda tomar. Como la enumeración DiaDeLaSemana solo tiene 7 casos posibles, no hay riesgo de que una variable de ese tipo adopte otro valor distinto a esos 7, por lo tanto no es necesario usar un default.

Sin embargo, si no hiciéramos mención a los 7 valores en los cases, deberíamos incluir un default:

switch mañana {
    case .lunes:
        print(“Mañana es lunes”)
    case .martes:
        print(“Mañana es martes”)
    case .miercoles:
        print(“Mañana es miércoles”)
    case .jueves:
        print(“Mañana es jueves”)
    case .viernes:
        print(“Mañana es viernes”)
    default:
        print(“Mañana comienza el fin de semana”)
}
//Devuelve
//Mañana es miércoles

Enumeraciones con métodos

Al igual que en las clases y structs, podemos definir métodos dentro de los enums. Esta característica muestra la flexibilidad que las enumeraciones tienen en Swift y lo diferencia con las implementaciones en otros lenguajes de programación.

Los métodos que escribamos dentro de un enum siguen las mismas reglas que vimos en el capítulo de funciones.

enum Saiyan {
    case Goku, Vegeta, Gohan, Trunks

    func superPoder() -> String {
        switch self {
            case .Goku, .Gohan:
                return "Kamehameha"
            case .Vegeta, .Trunks:
                return "Garlic Ho"
        }
    }
}

let principeSaiyan = Saiyan.Vegeta
print("\(principeSaiyan.superPoder())")

//Devuelve
//Garlic Ho