Constantes Swift: Struct ou Enum

Não tenho certeza qual dos dois é melhor para definir constantes. Uma estrutura ou um enum. Uma struct será copiada toda vez que eu usá-lo ou não? Quando eu penso em uma struct com static let constantes não faz sentido que ela seja copiada o tempo todo, na minha opinião. Mas se não for copiado, não importa o que eu faça?

Quais vantagens a escolha de uma struct ou enum?

Francisco diz usar Struct’s.

Ray Wunderlich diz usar Enum. Mas me falta a justificativa.

Ambas as estruturas e enumerações funcionam. Como exemplo, ambos

 struct PhysicalConstants { static let speedOfLight = 299_792_458 // ... } 

e

 enum PhysicalConstants { static let speedOfLight = 299_792_458 // ... } 

trabalhar e definir uma propriedade estática PhysicalConstants.speedOfLight .

Re: A struct será copiada toda vez que eu usá-lo ou não?

Tanto struct quanto enum são tipos de valor, de modo que também se aplicariam a enumerações. Mas isso é irrelevante aqui porque você não precisa criar um valor: as propriedades estáticas (também chamadas de propriedades de tipo ) são propriedades do próprio tipo, não de uma instância desse tipo.

Quais vantagens tem a escolha de uma struct ou enum?

Conforme mencionado no artigo vinculado :

A vantagem de usar uma enumeração sem maiúsculas e minúsculas é que ela não pode ser acidentalmente instanciada e funciona como um namespace puro.

Então, para uma estrutura,

 let foo = PhysicalConstants() 

cria um valor (inútil) do tipo PhysicalConstants , mas para uma enumeração sem maiúsculas e minúsculas, ele não compila:

 let foo = PhysicalConstants() // error: 'PhysicalConstants' cannot be constructed because it has no accessible initializers 

Aqui está uma resposta curta: Suas constantes precisam ser únicas? Em seguida, use um enum, que reforça isso.

Deseja usar várias constantes diferentes para conter o mesmo valor (geralmente útil para maior clareza)? Em seguida, use uma estrutura, o que permite isso.

Usando o Xcode 7.3.1 e o Swift 2.2

Embora eu concorde com Martin R, e o guia de estilo Ray Wenderlich faça um bom argumento de que as enums são melhores em quase todos os casos de uso, por ser um namespace puro, há um lugar em que usar um struct supera as enums .

Trocar declarações

Vamos começar com a versão da estrutura:

 struct StaticVars { static let someString = "someString" } switch "someString" { case StaticVars.someString: print("Matched StaticVars.someString") default: print("Didn't match StaticVars.someString") } 

Usando uma estrutura, isso corresponderá e imprimirá Matched StaticVars.someString .

Agora vamos considerar a versão de enum sem checkbox (mudando apenas a palavra-chave struct para enum ):

 enum StaticVars { static let someString = "someString" } switch "someString" { case StaticVars.someString: print("Matched StaticVars.someString") default: print("Didn't match StaticVars.someString") } 

Você perceberá que obtém um erro de tempo de compilation na instrução switch na linha case StaticVars.someString: . O erro é o Enum case 'someString' not found in type 'String' .

Há uma pseudo-solução alternativa convertendo a propriedade static em um encerramento que retorna o tipo.

Então você mudaria assim:

 enum StaticVars { static let someString = { return "someString" } } switch "someString" { case StaticVars.someString(): print("Matched StaticVars.someString") default: print("Didn't match StaticVars.someString") } 

Observe a necessidade de parênteses na instrução case porque agora é uma function.

A desvantagem é que agora que fizemos uma function, ela é executada toda vez que é invocada. Então, se é apenas um tipo primitivo simples como String ou Int , isso não é tão ruim. É essencialmente uma propriedade computada. Se for uma constante que precisa ser calculada e você deseja apenas calculá-la uma vez, considere computá-la em uma propriedade diferente e retornar o valor já computado no encerramento.

Você também pode replace o inicializador padrão por um privado e, em seguida, obterá o mesmo tipo de erro de tempo de compilation do que com o enum sem checkbox.

 struct StaticVars { static let someString = "someString" private init() {} } 

Mas com isso, você gostaria de colocar a declaração da estrutura em seu próprio arquivo, porque se você a declarasse no mesmo arquivo como, digamos, uma class View Controller, o arquivo dessa class ainda seria capaz de instanciar acidentalmente um inútil. instância do StaticVars , mas fora do arquivo da class, ele funcionaria como planejado. Mas é seu chamado.