Estou criando um cliente Reddit para fins de aprendizado. Eu preciso ter um arquivo com constantes nele. Eu estava pensando em importar o arquivo no Reddit-Prefix.pch
arquivo para disponibilizar as constantes para todos os arquivos. É uma boa maneira de fazer as coisas? Além disso, fiz minha pesquisa e encontrei vários métodos para criar constantes, mas não sei qual usar:
#define
macroconst
static const
extern const
enum
Então, qual o caminho preferido? Qual é a convenção? Eu sei que "depende", mas minha pergunta é mais específica: quais são os casos de uso para cada uma dessas soluções?
Além disso, se estiver usando extern const
, preciso importar o arquivo ou as constantes estarão disponíveis globalmente sem importar o arquivo?
Uma coisa que eu poderia concluir logicamente é que enum
é a melhor escolha ao definir algo como domínios de erro personalizados (estou realmente certo?). Mas e os outros?
fonte
enum
é útil apenas para valores integrais.#define
e constantes podem ser qualquer tipo de dados.const
,,static const
eextern const
são todos iguais, exceto no escopo. Portanto, existem realmente apenas três opções.Respostas:
A primeira pergunta é qual o escopo que você deseja que suas constantes tenham, que são realmente duas perguntas:
Se eles são específicos e internos a uma única classe, declare-os como
static const
na parte superior do arquivo .m, da seguinte maneira:Se eles pertencem a uma única classe, mas devem ser públicos / usados por outras classes, declare-os como
extern
no cabeçalho e defina-os no .m:Se eles devem ser globais, declare-os em um cabeçalho e defina-os em um módulo correspondente, especificamente para essas constantes.
Você pode misturá-las e combiná-las para diferentes constantes com diferentes níveis de quão global você deseja que sejam e para diferentes constantes globais que simplesmente não pertencem juntas - você pode colocá-las em módulos separados, cada um com seu próprio cabeçalho, se você quer.
Por que não
#define
?A resposta antiga é “macros não possuem informações de tipo”, mas hoje os compiladores são bastante inteligentes em fazer toda a verificação de tipos de literais (para os quais as macros se expandem) e também de variáveis.
A resposta moderna é porque o depurador não saberá sobre suas macros. Você não pode dizer
[myThing addObserver:self forKey:MyThingNotificationKey]
em um comando debugger seMyThingNotificationKey
é uma macro; o depurador só pode saber se for uma variável.Por que não
enum
?Bem, rmaddy me venceu nos comentários:
enum
só pode definir constantes inteiras. Coisas como números de identificação serial, máscaras de bits, códigos de quatro bytes, etc.Para esses fins,
enum
é ótimo e você absolutamente deve usá-lo. (Melhor ainda, use as teclasNS_ENUM
eNS_OPTIONS
.) Para outras coisas, você deve usar outra coisa;enum
não faz nada além de números inteiros.E outras perguntas
Provavelmente inofensivo, mas provavelmente excessivo. Importe os cabeçalhos das constantes para onde precisar deles.
#define
: Bastante limitado. Sinceramente, não tenho certeza de que exista uma boa razão para usar isso para constantes.const
: Melhor para constantes locais. Além disso, você deve usar isso para o que você declarou em um cabeçalho e agora está definindo.static const
: Melhor para constantes específicas de arquivo (ou classe).extern const
: Você deve usar isso ao exportar uma constante em um cabeçalho.Você precisa importar o arquivo, em cada arquivo em que o usa ou no cabeçalho do prefixo.
fonte
static NSString *const
o.h
arquivo completamente?static NSString *const foo = @"foo";
, seu cabeçalho determinará qual é a string e deve ser a mesma em todos os lugares - se você alterar a string e diferentes partes usarem versões diferentes do cabeçalho com uma string diferente, as strings não corresponderão na execução Tempo. Em uma estrutura, você deseja fornecer acesso apenas ao símbolo e permitir que a estrutura seja a única fonte do verdadeiro valor desse símbolo, para que todos obtenham a mesma string em um só lugar. Isso é o queextern
você recebe.#define
s: não é garantido que eles tenham o mesmo endereço na memória (dependendo de como são declarados, eles podem alocar uma nova instância toda vez que são usados); portanto, o usomyObject == MyDefine
nem sempre funciona como o esperado, masmyObject == MyStaticConst
vai.static NSString *const
vez destatic NSString const*
?? Alguma diferença ?!static NSString const *
é o mesmo questatic const NSString *
e significa "um ponteiro (mutável) para um NSString constante" - que é um pouco inútil aqui, já que o NSString já é imutável. O que você deseja apenasstatic NSString * const
- que é um "ponteiro constante para um NSString"FOUNDATION_EXPORT
Considere usar
FOUNDATION_EXPORT
um pouco mais de compatibilidade doextern
que é definido na base e compila em formatos compatíveis para C, C ++ e Win32.Conforme definido em NSObjCRuntime.h
fonte