() translation by (you can also view the original English article)
Las enumeraciones son un patrón de diseño común en muchos lenguajes de programación. Mientras que usted puede estar familiarizado con las enumeraciones en C y Objective-C, implementación de las enumeraciones en Swift es significativamente más potente y flexible. En este Consejo rápido, usted aprenderá lo especial acerca de enumeraciones en Swift, cómo utilizarlos en tus proyectos y lo que los hace tan poderoso.
1. ¿Qué es una Enumeración?
Las enumeraciones no son nuevas, y ciertamente no son únicos a Swift. Sin embargo, si estás familiarizado con enumeraciones en C, entonces va a encantar poderosos de Swift en tomar enumeraciones.
Si las enums o enumeraciones son nuevas para usted, entonces no es familiar con lo que tienen que ofrecer. En Swift, enumeraciones son tipos de primera clase que definen una lista de posibles valores de ese tipo.
Un ejemplo podría ser los posibles estados de una conexión de red. Los Estados posibles podrían ser:
- desconecta
- conectando
- conectado
Podríamos añadir que un cuarto estado para el caso el estado es desconocido. Con este ejemplo en mente, vamos a ver cómo definir e implementar tal enumeración.
Conceptos Básicos
Como dije, las enumeraciones son tipos de primera clase en Swift. Una definición de enumeración es muy similar a una definición de clase o estructura. En el ejemplo siguiente, definimos la enumeración ConnectionState
.
1 |
enum ConnectionState { |
2 |
|
3 |
}
|
El nombre de la enumeración es precedido por la palabra clave enum
y seguido por un par de llaves. La enumeración ConnectionState
definirá los posibles estados de una conexión de red. Para definir estos estados, añadimos valores miembro o miembros a la definición de la enumeración. La definición de un valor de miembro siempre comienza con la palabra clave case
.
1 |
enum ConnectionState { |
2 |
case Unknown |
3 |
case Disconnected |
4 |
case Connecting |
5 |
case Connected |
6 |
}
|
En C o en Objective-C, la enumeración anterior se vería un poco diferente como se ilustra en el ejemplo siguiente. Cada valor de la enumeración corresponde con un entero, por ejemplo, ConnectionStateUnknown
es igual a 0
, ConnectionStateDisconnected
es igual a 1
, etcetera.
1 |
typedef enum : NSUInteger { |
2 |
ConnectionStateUnknown, |
3 |
ConnectionStateDisconnected, |
4 |
ConnectionStateConnecting, |
5 |
ConnectionStateConnected
|
6 |
} ConnectionState; |
Esto no es cierto en Swift. Los miembros de una enumeración no corresponden automáticamente con un valor entero. Los miembros de la enumeración ConnectionState
son los valores propios y son de tipo ConnectionState
. Esto hace que trabajar con enumeraciones más seguro y más explícito.
Valores Brutos
Es posible especificar explícitamente los valores de los miembros de una enumeración. En el ejemplo siguiente, los miembros de la enumeración ConnectionState
tienen un valor bruto de tipo int
. Cada miembro se asigna un valor bruto, correspondiente con un número entero.
1 |
enum ConnectionState: Int { |
2 |
case Unknown = -1 |
3 |
case Disconnected = 0 |
4 |
case Connecting = 1 |
5 |
case Connected = 2 |
6 |
}
|
Tenga en cuenta que nos especifique el tipo de los valores brutos en la definición de la enumeración y que los dos valores no pueden tener el mismo valor bruto. Si sólo especifica un valor para el miembro Unknown
, entonces Swift automáticamente incrementar el valor del miembro Unknown
y asignar valores a los demás miembros de la enumeración. Para ilustrar mejor esto, el ejemplo es idéntica a la anterior definición de la enumeración ConnectionState
.
1 |
enum ConnectionState: Int { |
2 |
case Unknown = -1 |
3 |
case Disconnected |
4 |
case Connecting |
5 |
case Connected |
6 |
}
|
2. Trabajando con Enumeraciones
Inicialización
Mediante la enumeración ConnectionState
es similar a usar cualquier otro tipo de Swift. En el siguiente ejemplo, declaramos una variable, connectionState
y establezca su valor en ConnectionState.Connecting
.
1 |
var connectionState = ConnectionState.Connecting |
El valor de connectionState
es ConnectionState.Connecting
y la variable es de tipo ConnectionState
.
Inferencia de este tipo en SWIFT es muy conveniente cuando se trabaja con enumeraciones. Porque declaramos connectionState
como de tipo ConnectionState
, ahora podemos asignar un nuevo valor utilizando la sintaxis de punto de taquigrafía para enumeraciones.
1 |
connectionState = .Connected |
Control de Flujo
Usando enumeraciones en un if
o sentencia switch
es sencillo. Recuerde que declaraciones switch
tienen que ser exhaustiva. Agregue un caso default
(predeterminado) si es necesario.
1 |
enum ConnectionState { |
2 |
case Unknown |
3 |
case Disconnected |
4 |
case Connecting |
5 |
case Connected |
6 |
}
|
7 |
|
8 |
var connectionState = ConnectionState.Connecting |
9 |
|
10 |
connectionState = .Connected |
11 |
|
12 |
switch connectionState { |
13 |
case .Disconnected: |
14 |
println("Disconnected") |
15 |
case .Connecting: |
16 |
println("Connecting") |
17 |
case .Connected: |
18 |
println("Connected") |
19 |
default: |
20 |
println("Unknown State") |
21 |
}
|
En el ejemplo siguiente se muestra cómo utilizar la enumeración ConnectionState
. También muestra cómo obtener acceso al valor asociado de un miembro de enumeración. La función canConnect
acepta una instancia de ConnectionState
y devuelve un Bool
.
1 |
func canConnect(connectionState: ConnectionState) -> Bool { |
2 |
var result = false |
3 |
|
4 |
switch connectionState { |
5 |
case .Connected(let port): |
6 |
if port == 3000 { |
7 |
result = true |
8 |
}
|
9 |
default: |
10 |
result = false |
11 |
}
|
12 |
|
13 |
return result |
14 |
}
|
15 |
|
16 |
let state = ConnectionState.Connected(3000) |
17 |
|
18 |
if canConnect(state) { |
19 |
// ...
|
20 |
}
|
La función canConnect
sólo devuelve true
si la instancia de ConnectionState
pasada a la función Conected
y su valor asociado int
igual a 3000
. Tenga en cuenta que el valor asociado del miembro connected
está disponible en la declaración del switch
como una constante llamada port
, que luego podemos utilizar en el case
correspondiente.
3. Valores Asociados
Otra característica atractiva de las enumeraciones Swift son valores asociados. Cada miembro de una enumeración puede tener un valor asociado. Valores asociados son muy flexibles. Por ejemplo, valores asociados de diferentes miembros de la misma enumeración no necesitan ser del mismo tipo. Echa un vistazo en el siguiente ejemplo para entender mejor el concepto de valores asociados.
1 |
enum ConnectionState { |
2 |
case Unknown |
3 |
case Disconnected |
4 |
case Connecting(Int, Double) |
5 |
case Connected(Int) |
6 |
}
|
Los miembros Unknown
y Disconnected
no tienen un valor asociado. El miembro Connecting
tiene un valor asociado de tipo (Int, Double)
, especificando el intervalo de número y tiempo de espera del puerto de la conexión. El miembro Connected
tiene un valor de tipo Int
, especificando el número de puerto asociado.
Es importante entender que un valor asociado es vinculado o asociado con un miembro de la enumeración. Valor del miembro permanece inalterado. En el ejemplo siguiente se muestra cómo crear una instancia de ConnectionState
con un valor asociado.
1 |
var connectionState = ConnectionState.Connecting(3000, 30.0) |
4. Métodos y Tipos de Valor
Métodos
Las enumeraciones son bastante poderosas en Swift. Enumeraciones pueden definir métodos, tales como un inicializador para seleccionar un valor de miembro predeterminado si no se especificó.
1 |
enum ConnectionState { |
2 |
case Unknown |
3 |
case Disconnected |
4 |
case Connecting(Int, Double) |
5 |
case Connected(Int) |
6 |
|
7 |
init () { |
8 |
self = .Unknown |
9 |
}
|
10 |
}
|
11 |
|
12 |
var connectionState = ConnectionState() // .Unknown |
En este ejemplo, inicializamos una instancia de la enumeración ConnectionState
sin especificar explícitamente un valor para él. En el inicializador de la enumeración, sin embargo, hemos creado la instancia de Unknown
. El resultado es que la variable connectionState
es igual a ConnectionState.Unknown
.
Tipos de Valor
Como estructuras, las enumeraciones son tipos de valor, lo que significa que una enumeración no se pasa por referencia, como instancias de clase, sino por valor. En el siguiente ejemplo ilustra esto.
1 |
var connectionState1 = ConnectionState() |
2 |
var connectionState2 = connectionState1 |
3 |
|
4 |
connectionState1 = .Connected(1000) |
5 |
|
6 |
println(connectionState1) // .Connected(1000) |
7 |
println(connectionState2) // .Unknown |
A pesar de asignar connectionState1
a connectionState2
, los valores de connectionState1
y connectionState2
son diferentes al final del ejemplo.
Cuando connectionState1
se asigna a connectionState2
, crea una copia de connectionState1
y Swift asigna esto a connectionState2
. En otras palabras, connectionState1
y connectionState2
se refieren a dos distintas instancias de ConnectionState
.
Conclusión
Enumeraciones en Swift son increíblemente poderosas en comparación con, por ejemplo, las enumeraciones en C. Uno de los aspectos más poderosos de las enumeraciones es que son un tipo de primera clase en Swift. Tipo de seguridad es un aspecto clave de la lenguaje Swift y las enumeraciones encajan perfectamente en esa mentalidad.