swift - Constantes rápidas: estructura o enumeración
enums constants (3)
No estoy seguro de cuál de los dos es mejor para definir 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, ¿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 que use Enum''s. Pero me falta la justificación.
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 el uso de una
struct
triunfa sobre las
enums
.
Cambiar declaraciones
Comencemos con la versión de estructura:
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 caso (solo cambiando la
struct
la palabra clave 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 compilación en la declaración de cambio en el
case StaticVars.someString:
line.
El error es el
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 declaración del 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 solo un tipo primitivo simple como
String
o
Int
, esto no es tan malo.
Es esencialmente una propiedad computada.
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 compilación que con la enumeración sin mayúsculas y minúsculas.
struct StaticVars {
static let someString = "someString"
private init() {}
}
Pero con esto, querrás poner la declaración de la estructura en su propio archivo, porque si la declaraste en el mismo archivo que, por ejemplo, una clase de Controlador de Vista, el archivo de esa clase aún podría instanciar accidentalmente un inútil instancia de
StaticVars
, pero fuera del archivo de la clase funcionaría según lo previsto.
Pero es tu decisión.
Aquí hay una respuesta corta: ¿Tus constantes deben ser únicas? Luego use una enumeración, que hace cumplir esto.
¿Desea utilizar varias constantes diferentes para contener el mismo valor (a menudo útil para mayor claridad)? Luego use una estructura, que permite esto.
Tanto las estructuras como las 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: ¿Se copiará una estructura cada vez que la use o no?
Tanto
struct
como
enum
son tipos de valor, por lo que también se aplicarían a las enumeraciones.
Pero eso es
irrelevante
aquí porque no tiene que crear ningún valor: las propiedades estáticas (también llamadas propiedades de
tipo
) son propiedades del tipo en sí, no de una instancia de ese tipo.
Re: ¿Qué ventajas tiene la elección de una estructura o enumeración?
Como se menciona en el artículo vinculado a :
La ventaja de usar una enumeración sin mayúsculas y minúsculas 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 sin mayúsculas y minúsculas no se compila:
let foo = PhysicalConstants()
// error: ''PhysicalConstants'' cannot be constructed because it has no accessible initializers