Estoy creando un cliente Reddit con fines de aprendizaje. Necesito tener un archivo con constantes. Estaba pensando en importar el archivo en el Reddit-Prefix.pch
archivo para que las constantes estén disponibles para todos los archivos. ¿Es una buena forma de hacer las cosas? Además, hice mi investigación y encontré varios métodos para crear constantes, pero no sé cuál usar:
#define
macroconst
static const
extern const
enum
Entonces, ¿cuál es la forma preferida? ¿Qué es la convención? Sé que "depende", pero mi pregunta más específica es: ¿Cuáles son los casos de uso para cada una de esas soluciones?
Además, si lo uso extern const
, ¿necesito importar el archivo, o las constantes estarán disponibles globalmente sin importar el archivo?
Una cosa que podría concluir lógicamente es que enum
es la mejor opción al definir algo como dominios de error personalizados (¿estoy realmente en lo cierto?). ¿Pero qué hay de los demás?
fuente
enum
solo es útil para valores integrales.#define
y las constantes pueden ser de cualquier tipo de datos.const
,static const
yextern const
son todos iguales excepto por el alcance. Entonces, en realidad solo hay tres opciones.Respuestas:
La primera pregunta es qué alcance desea que tengan sus constantes, que en realidad son dos preguntas:
Si son específicos e internos de una sola clase, declare como
static const
en la parte superior del archivo .m, así:Si pertenecen a una sola clase pero deben ser públicas / utilizadas por otras clases, declare como
extern
en el encabezado y defínalos en el .m:Si deben ser globales, declararlos en un encabezado y definirlos en un módulo correspondiente, específicamente para esas constantes.
Puede mezclarlos y combinarlos para diferentes constantes con diferentes niveles de cuán global desea que sean, y para diferentes constantes globales que simplemente no pertenecen juntas; puede colocarlas en módulos separados, cada uno con su propio encabezado, si querer.
¿Por qué no
#define
?La vieja respuesta es "las macros no tienen información de tipo", pero los compiladores de hoy en día son bastante inteligentes al hacer toda la verificación de tipo para los literales (a qué se expanden las macros) y las variables.
La respuesta moderna es porque el depurador no sabrá sobre sus macros. No se puede decir
[myThing addObserver:self forKey:MyThingNotificationKey]
en un comando de depurador siMyThingNotificationKey
es una macro; el depurador solo puede saberlo si es una variable.¿Por qué no
enum
?Bueno, rmaddy me ganó en los comentarios:
enum
solo puede definir constantes enteras. Cosas como números de identificación de serie, máscaras de bits, códigos de cuatro bytes, etc.Para esos fines,
enum
es genial y absolutamente deberías usarlo. (Aún mejor, use las macrosNS_ENUM
yNS_OPTIONS
.) Para otras cosas, debe usar otra cosa;enum
no hace nada más que enteros.Y otras preguntas
Probablemente inofensivo, pero probablemente excesivo. Importe sus encabezados constantes donde los necesite.
#define
: Bastante limitado. Honestamente, no estoy seguro de que haya una buena razón para usar esto para las constantes.const
: Lo mejor para las constantes locales. Además, debe usar esto para uno que declaró en un encabezado y que ahora está definiendo.static const
: Mejor para constantes específicas de archivo (o específicas de clase).extern const
: Debe usar esto al exportar una constante en un encabezado.Debe importar el archivo, ya sea en cada archivo donde lo usa o en el encabezado del prefijo.
fuente
static NSString *const
en el.h
archivo por completo?static NSString *const foo = @"foo";
, su encabezado determina cuál es la cadena, y debe ser la misma en todas partes: si alguna vez cambia la cadena y las diferentes partes usan diferentes versiones del encabezado con una cadena diferente, las cadenas no coincidirán en la ejecución hora. En un marco, desea proporcionar acceso solo al símbolo y dejar que el marco sea la única fuente del verdadero valor de ese símbolo, para que todos obtengan la misma cadena desde un solo lugar. Eso es lo queextern
te atrapa.#define
s: no se garantiza que tengan la misma dirección en la memoria (dependiendo de cómo se declaren, pueden asignar una nueva instancia cada vez que se usan), por lo que el usomyObject == MyDefine
no siempre funcionará como se esperaba, pero lomyObject == MyStaticConst
haré.static NSString *const
lugar destatic NSString const*
?? ¿Alguna diferencia?static NSString const *
es lo mismostatic const NSString *
y significa "un puntero (variable) a una NSString constante", lo cual es un poco inútil aquí ya que NSString ya es inmutable. Lo que solo quieresstatic NSString * const
, que es un "puntero constante a un NSString"FOUNDATION_EXPORT
Considere usar
FOUNDATION_EXPORT
un poco más de compatibilidad queextern
ya que está definido en la base y compila a formatos compatibles para C, C ++ y Win32.Como se define en NSObjCRuntime.h
fuente