Je crée un client Reddit à des fins d'apprentissage. J'ai besoin d'un fichier contenant des constantes. Je pensais importer le fichier dans le Reddit-Prefix.pch
fichier pour rendre les constantes disponibles à tous les fichiers. Est-ce une bonne façon de faire les choses? Aussi, j'ai fait mes recherches et trouvé plusieurs méthodes pour créer des constantes, mais je ne sais pas laquelle utiliser:
#define
macroconst
static const
extern const
enum
Alors, quelle est la voie préférée? Quelle est la convention? Je sais que "ça dépend" mais ma question plus spécifiquement est: Quels sont les cas d'utilisation de chacune de ces solutions?
De plus, si vous utilisez extern const
, dois-je importer le fichier, ou les constantes seront-elles disponibles globalement sans importer le fichier?
Une chose que je pourrais logiquement conclure est que enum
c'est le meilleur choix pour définir quelque chose comme des domaines d'erreur personnalisés (ai-je vraiment raison?). Mais qu'en est-il des autres?
la source
enum
n'est utile que pour les valeurs intégrales.#define
et les constantes peuvent être de n'importe quel type de données.const
,static const
etextern const
sont tous identiques sauf pour la portée. Il n'y a donc vraiment que trois choix.Réponses:
La première question est de savoir quelle portée vous voulez que vos constantes aient, qui sont en réalité deux questions:
S'ils sont spécifiques et internes à une seule classe, déclarez-les en
static const
haut du fichier .m, comme ceci:S'ils appartiennent à une seule classe mais devraient être publics / utilisés par d'autres classes, déclarez-les comme
extern
dans l'en-tête et définissez-les dans le .m:Si elles doivent être globales, déclarez-les dans un en-tête et définissez-les dans un module correspondant, spécifiquement pour ces constantes.
Vous pouvez les mélanger et les assortir pour différentes constantes avec différents niveaux de globalité que vous voulez qu'elles soient, et pour différentes constantes globales qui ne vont tout simplement pas ensemble - vous pouvez les mettre dans des modules séparés, chacun avec son propre en-tête, si vous vouloir.
Pourquoi pas
#define
?La vieille réponse est «les macros n'ont pas d'informations de type», mais les compilateurs d'aujourd'hui sont assez intelligents pour faire tout le contrôle de type pour les littéraux (vers lesquels les macros s'étendent) ainsi que pour les variables.
La réponse moderne est que le débogueur ne connaîtra pas vos macros. Vous ne pouvez pas dire
[myThing addObserver:self forKey:MyThingNotificationKey]
dans une commande de débogage siMyThingNotificationKey
est une macro; le débogueur ne peut le savoir que s'il s'agit d'une variable.Pourquoi pas
enum
?Eh bien, rmaddy m'a battu dans les commentaires:
enum
ne peut définir que des constantes entières. Des choses comme les numéros d'identification de série, les masques binaires, les codes à quatre octets, etc.À ces fins,
enum
c'est génial et vous devez absolument l'utiliser. (Encore mieux, utilisez les macrosNS_ENUM
etNS_OPTIONS
.) Pour d'autres choses, vous devez utiliser autre chose;enum
ne fait rien d'autre que des entiers.Et d'autres questions
Probablement inoffensif, mais probablement excessif. Importez vos en-têtes de constantes là où vous en avez besoin.
#define
: Assez limité. Honnêtement, je ne suis pas sûr qu'il y ait une bonne raison d'utiliser cela pour les constantes.const
: Idéal pour les constantes locales. De plus, vous devez l'utiliser pour celui que vous avez déclaré dans un en-tête et que vous définissez maintenant.static const
: Idéal pour les constantes spécifiques au fichier (ou à la classe).extern const
: Vous devez l'utiliser lors de l'exportation d'une constante dans un en-tête.Vous devez importer le fichier, soit dans chaque fichier où vous l'utilisez, soit dans l'en-tête du préfixe.
la source
static NSString *const
dans le.h
fichier?static NSString *const foo = @"foo";
, votre en-tête détermine ce qu'est la chaîne, et elle doit être la même partout - si jamais vous changez la chaîne et que différentes parties utilisent différentes versions de l'en-tête avec une chaîne différente, alors les chaînes ne correspondront pas à l'exécution temps. Dans un framework, vous souhaitez fournir un accès au symbole uniquement et laisser le framework être la seule source de la vraie valeur de ce symbole, afin que tout le monde obtienne la même chaîne d'un seul endroit. C'est ce quiextern
vous attire.#define
s: ils ne sont pas garantis d'avoir la même adresse en mémoire (selon la façon dont ils sont déclarés, ils peuvent allouer une nouvelle instance à chaque fois qu'ils sont utilisés), donc l'utilisationmyObject == MyDefine
ne fonctionnera pas toujours comme prévu, mais lemyObject == MyStaticConst
fera.static NSString *const
au lieu destatic NSString const*
?? Des différences?!static NSString const *
est le même questatic const NSString *
et signifie "un pointeur (modifiable) vers une NSString constante" - ce qui est un peu inutile ici car NSString est déjà immuable. Ce que vous voulez uniquementstatic NSString * const
- qui est un "pointeur constant vers une chaîne NSS"FOUNDATION_EXPORT
Pensez à utiliser
FOUNDATION_EXPORT
pour un peu plus de compatibilité queextern
car il est défini dans la fondation et compile aux formats compatibles pour C, C ++ et Win32.Tel que défini dans NSObjCRuntime.h
la source