Constantes Swift: Struct o Enum

No estoy seguro de cuál de los dos es mejor para definir las constantes. Una estructura o una enumeración. ¿Se copiará una estructura cada vez que la use o no? Cuando pienso en una estructura con constantes de static let no tiene sentido que se copie todo el tiempo, en mi opinión. Pero si no se copia, ¿entonces no importa lo que tome?

¿Qué ventajas tiene la elección de una estructura o enumeración?

Francisco dice usar Struct’s.

Ray Wunderlich dice usar Enum. Pero me falta la justificación.

Ambas estructuras y enumeraciones funcionan. Como ejemplo, ambos

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

y

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

trabajar y definir una propiedad estática PhysicalConstants.speedOfLight .

Re: Una estructura se copiará cada vez que lo uso o no?

Tanto struct como enum son tipos de valores, de modo que también se aplicarían a las enumeraciones. Pero eso es irrelevante aquí porque no tiene que crear un valor en absoluto: las propiedades estáticas (también llamadas propiedades de tipo ) son propiedades del tipo en sí mismas, no de una instancia de ese tipo.

Re: ¿Qué ventajas tiene la elección de una estructura o enum?

Como se menciona en el artículo vinculado a :

La ventaja de utilizar una enumeración sin case es que no se puede instanciar accidentalmente y funciona como un espacio de nombres puro.

Entonces para una estructura,

 let foo = PhysicalConstants() 

crea un valor (inútil) de tipo PhysicalConstants , pero para una enumeración case-case no se puede comstackr:

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

Aquí hay una respuesta breve: ¿Sus constantes deben ser únicas? Luego usa una enumeración, que hace cumplir esto.

¿Desea usar varias constantes diferentes para contener el mismo valor (a menudo útil para mayor claridad)? Luego usa una estructura, que permite esto.

Usando Xcode 7.3.1 y Swift 2.2

Si bien estoy de acuerdo con Martin R, y la guía de estilo de Ray Wenderlich señala que las enumeraciones son mejores en casi todos los casos de uso debido a que es un espacio de nombres puro, hay un lugar donde se usa una struct triunfa en las enums .

Cambiar declaraciones

Comencemos con la versión struct:

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

Usando una estructura, esto coincidirá e imprimirá Matched StaticVars.someString .

Ahora consideremos la versión enum sin carcasa (solo cambiando la palabra clave struct a enum ):

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

Notará que obtiene un error de tiempo de comstackción en la instrucción switch en el case StaticVars.someString: line. El error es Enum case 'someString' not found in type 'String' .

Hay una pseudo-solución al convertir la propiedad estática en un cierre que devuelve el tipo en su lugar.

Entonces lo cambiarías así:

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

Tenga en cuenta la necesidad de paréntesis en la statement de caso porque ahora es una función.

La desventaja es que ahora que lo hemos convertido en una función, se ejecuta cada vez que se invoca. Entonces, si es simplemente un tipo primitivo simple como String o Int , esto no es tan malo. Es esencialmente una propiedad calculada. Si es una constante que debe calcularse y solo desea calcularla una vez, considere calcularla en una propiedad diferente y devolver ese valor ya calculado en el cierre.

También puede anular el inicializador predeterminado con uno privado, y luego obtendrá el mismo tipo de bondad de error de tiempo de comstackción que con la enum sin carcasa.

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

Pero con esto, querrías poner la statement de la estructura en su propio archivo, porque si lo declaraste en el mismo archivo que, por ejemplo, una clase View Controller, el archivo de esa clase aún podría crear una instancia accidental de un inútil instancia de StaticVars , pero fuera del archivo de la clase funcionaría según lo previsto. Pero es tu decisión