() translation by (you can also view the original English article)
Enumerações é um padrão de projeto comum em muitas linguagens de programação. Mesmo você tendo conhecimento de enumerações em C e Objective-C, a implementação de enumerações em Swift é significativamente mais poderosa e flexível. Nesta dica rápida, você vai aprender o que há de especial sobre enumerações em Swift, como usá-los em seus projetos e o que as torna tão poderosas.
1. O que é uma Enumeração?
Enumerações não são novas e certamente não são exclusivas para Swift. Porém, se você está familiarizado com enumerações em C, você irá adorar o quão poderosa são enumerações em Swift.
Se enums ou enumerações são novas para você, então você pode não estar familiarizado com o que elas tem a te oferecer. Em Swift, enumerações são tipos de primeira classe que define uma lista de possibilidades de valores este cada tipo.
Um exemplo pode ser os possíveis estados de uma conexão de rede. Os possíveis estados poderiam ser:
- disconectado
- conectando
- conectado
Poderíamos adicionar um quarto estado para o caso de um estado desconhecido. Com este exemplo em mente, vamos ver como definir e implementar tal enumeração.
Básico
Como eu disse, enumerações são tipos de primeira classe no Swift. Uma definição de enumeração é muito similar a definição de uma classe ou estrutura. No exemplo a seguir, definimos a enumeração ConnectionState
.
1 |
enum ConnectionState { |
2 |
|
3 |
}
|
O nome da enumeração é precedido pela palavra-chave enum
e seguido por um par de chaves. A enumeração ConectionState
definirá os possíveis estados de uma conexão de rede. Para definir esses estados, adicionamos valores membro ou membros à definição da enumeração. A definição de um valor membro sempre começa com a palavra-chave case
.
1 |
enum ConnectionState { |
2 |
case Unknown |
3 |
case Disconnected |
4 |
case Connecting |
5 |
case Connected |
6 |
}
|
Em C ou Objective-C, a enumeração acima seria um pouco diferente, como ilustra o exemplo abaixo. Cada valor da enumeração corresponde a um inteiro, por exemplo, ConnectionStateUnknown
é igual a 0
, ConnectionStateDisconnected
é igual a 1
, etc.
1 |
typedef enum : NSUInteger { |
2 |
ConnectionStateUnknown, |
3 |
ConnectionStateDisconnected, |
4 |
ConnectionStateConnecting, |
5 |
ConnectionStateConnected
|
6 |
} ConnectionState; |
Não é assim em Swift. Os membros de uma enumeração não correspondem automaticamente com um valor inteiro. Os membros da enumeração ConnectionState
dão valores a si mesmos e são do tipo ConnectionState
. Isto faz com que o trabalho com enumerações seja mais seguro e mais explícito.
Valores Bruto
É possível especificar explicitamente os valores dos membros de uma enumeração. No exemplo a seguir, os membros da enumeração ConnectionState
tem um valor bruto do tipo Int
. Cada membro é atribuído a um valor bruto, correspondente com um inteiro.
1 |
enum ConnectionState: Int { |
2 |
case Unknown = -1 |
3 |
case Disconnected = 0 |
4 |
case Connecting = 1 |
5 |
case Connected = 2 |
6 |
}
|
Note que especificamos o tipo do valor bruto na definição da enumeração e que dois valores membro não podem ter o mesmo valor bruto. Se especificarmos apenas um valor para o membro Unknown
, então o Swift automaticamente incrementa o valor do membro Unknown
e atribuir valores únicos para os outros membros da enumeração. Para melhor ilustrar isto, o exemplo abaixo é idêntico à definição anterior da enumeração ConnectionState
.
1 |
enum ConnectionState: Int { |
2 |
case Unknown = -1 |
3 |
case Disconnected |
4 |
case Connecting |
5 |
case Connected |
6 |
}
|
2. Trabalhando com Enumerações
Inicialização
Usar a enumeração ConnectionState
é semelhante ao uso de qualquer outro tipo em Swift. No próximo exemplo, declaramos uma variável, connectionState
, e definimos seu valor com ConnectionState.Connectiong
.
1 |
var connectionState = ConnectionState.Connecting |
O valor de connectionState
é ConnectionState.Connecting
e a variável é do tipo ConnectionState
.
Inferência de tipo do Swift é muito conveniente quando se trabalha com enumerações. Como declaramos connectionState
como sendo do tipo ConnectionState
, agora podemos atribuir um novo valor usando a sintaxe de ponto para a enumeração.
1 |
connectionState = .Connected |
Controle de Fluxo
Usar enumerações em uma instrução if
ou switch
é fácil. Lembre-se que instruções switch
precisam ser exaustiva. Adicione um caso default
se necessário.
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 |
}
|
O exemplo a seguir demonstra como a enumeração ConnectionState
pode ser usada. Ele também mostra como acessar o valor associado de um membro de enum. A função canConnect
recebe uma instância ConnectionState
e retorna um 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 |
}
|
A função canConnect
retorna true
apenas se a instânciaConnectionState
passada para a função for igual a .Connected
e seu valor associado for um Int
igual a 3000
. Note que o valor associada do membro Connected
é acessível na instrução switch
como uma constante com o nome port
, que podemos usar no case
correspondente.
3. Valores Associados
Outro recurso atraente de enums em Swift são valores associados. Cada membro de um enum pode ter um valor associado. Valores associados são muito flexiveis. Por exemplo, valores associados de diferentes membros de um mesmo enum não precisam ser do mesmo tipo. Dê uma olhada no exemplo a seguir para entender melhor o conceito de valores associados.
1 |
enum ConnectionState { |
2 |
case Unknown |
3 |
case Disconnected |
4 |
case Connecting(Int, Double) |
5 |
case Connected(Int) |
6 |
}
|
Os membros Unknown
e Disconnected
não tem um valor associado. O membro Connecting
tem um valor associado do tipo (Int, Double)
, especificando o número da porta e o intervalo de tempo da conexão. O membro Connected
tem um valor associado do tipo Int
, especificando o número da porta.
É importante entender que um valor associado é ligado ou associado com um membro da enumeração. O valor do membro permanece inalterado. O próximo exemplo demonstra como criamos uma instância ConnectionState
com um valor associado.
1 |
var connectionState = ConnectionState.Connecting(3000, 30.0) |
4. Métodos e Tipos de Valores
Métodos
Enumerações são muito poderosas em Swift. Enumerações podem até mesmo definir métodos, tais como um inicializador para selecionar um valor de membro padrão se nenhum foi especificado.
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 |
Neste exemplo, inicializamos uma instância da enumeração ConnectionState
sem especificar explicitamente um valor para ele. No inicializador da enumeração, no entanto, definimos a instância para o Unknown
. O resultado é que a variável connectionState
é igual a ConnectionState.Unknown
.
Tipos de Valores
Como estruturas, enumerações são tipo de valor, o que significa que uma enumeração não é passada como referência, como a instância de uma classe, mas como valor. O exemplo a seguir demonstra isso.
1 |
var connectionState1 = ConnectionState() |
2 |
var connectionState2 = connectionState1 |
3 |
|
4 |
connectionState1 = .Connected(1000) |
5 |
|
6 |
println(connectionState1) // .Connected(1000) |
7 |
println(connectionState2) // .Unknown |
Mesmo que atribuímos connectionState1
para connectionState2
, os valores de connectionState1
e connectionState2
são diferentes no final do exemplo.
Quando connectionState1
é atribuído a connectionState2
, o Swift cria uma cópia do connectionState1
e atribui isso à connectionState2
. Em outras palavras, connectionState1
e connectionState2
referem-se a duas instâncias diferentes de ConnectionState
.
Conclusão
Enums em Swift é incrivelmente poderosas comparadas, por exemplo, a enums em C. Um dos aspectos mais poderoso da enumerações é que ela é de primeira classe em Swift. Type safety é um aspecto-chave da linguagem Swift e enumerações se encaixam perfeitamente nessa mentalidade.
Seja o primeiro a saber sobre novas traduções–siga @tutsplus_pt no Twitter!