Я создаю клиент Reddit для учебных целей. Мне нужно иметь файл с константами в нем. Я думал об импорте файла в Reddit-Prefix.pch
файл, чтобы сделать константы доступными для всех файлов. Это хороший способ делать вещи? Кроме того, я провел исследование и нашел несколько методов для создания констант, но я не знаю, какой из них использовать:
#define
макросconst
static const
extern const
enum
Так какой путь является предпочтительным? Что такое конвенция? Я знаю, что «это зависит», но мой вопрос более конкретно: каковы варианты использования для каждого из этих решений?
Также, если вы используете extern const
, нужно ли импортировать файл, или константы будут доступны глобально без импорта файла?
Я мог бы логично сделать вывод, что enum
это лучший выбор при определении чего-то вроде пользовательских доменов ошибок (на самом деле я прав?). А что насчет остальных?
источник
enum
полезно только для интегральных значений.#define
и константы могут быть любого типа данных.const
,static const
Иextern const
все же за исключением объема. Так что на самом деле есть только три варианта.Ответы:
Первый вопрос заключается в том, какую область видимости вы хотите иметь для своих констант, а на самом деле это два вопроса:
Если они являются специфическими и внутренними для одного класса, объявите их
static const
в начале файла .m следующим образом:Если они относятся к одному классу, но должны быть публичными / использоваться другими классами, объявите их как
extern
в заголовке и определите их в .m:Если они должны быть глобальными, объявите их в заголовке и определите их в соответствующем модуле, специально для этих констант.
Вы можете смешивать и сопоставлять их для разных констант с разными уровнями того, насколько глобальными они вам нужны, и для разных глобальных констант, которые просто не связаны друг с другом - вы можете поместить их в отдельные модули, каждый со своим собственным заголовком, если вы хотеть.
Почему нет
#define
?Старый ответ - «у макросов нет информации о типе», но сегодня компиляторы достаточно умны в отношении выполнения всей проверки типов для литералов (то, к чему расширяются макросы), а также для переменных.
Современный ответ таков: отладчик не будет знать о ваших макросах. Вы не можете сказать
[myThing addObserver:self forKey:MyThingNotificationKey]
в команде отладчика,MyThingNotificationKey
является ли макрос; отладчик может знать об этом, только если это переменная.Почему нет
enum
?Что ж, rmaddy опередил меня в комментариях:
enum
может определять только целочисленные константы. Такие вещи, как номера серийных идентификаторов, битовые маски, четырехбайтовые коды и т. Д.Для этих целей
enum
отлично подходит, и вы обязательно должны его использовать. (Еще лучше, если использовать теNS_ENUM
иNS_OPTIONS
макросы .) Для других вещей, вы должны использовать что - то другое;enum
не делает ничего, кроме целых чисел.И другие вопросы
Вероятно, безвреден, но, вероятно, чрезмерен. Импортируйте ваши константы заголовков, где они вам нужны.
#define
Довольно ограничен. Я, честно говоря, не уверен, что есть веская причина использовать это для констант больше.const
: Лучше всего подходит для локальных констант. Кроме того, вы должны использовать это для того, который вы объявили в заголовке и теперь определяете.static const
: Лучше всего подходит для констант, специфичных для файлов (или классов).extern const
: Вы должны использовать это при экспорте константы в заголовке.Вам необходимо импортировать файл, либо в каждый файл, в котором вы его используете, либо в заголовок префикса.
источник
static NSString *const
в.h
файле вообще?static NSString *const foo = @"foo";
, то ваш заголовок определяет, что это за строка, и она должна быть везде одинаковой - если вы когда-нибудь измените строку, и разные стороны будут использовать разные версии заголовка с другой строкой, то строки при запуске не будут совпадать время. В платформе вы хотите предоставить доступ только к символу и позволить платформе быть единственным источником истинного значения этого символа, чтобы все получали одну и ту же строку из одного места. Вот чтоextern
тебя заводит.#define
s: у них не гарантируется одинаковый адрес в памяти (в зависимости от того, как они объявлены, они могут выделять новый экземпляр при каждом использовании), поэтому использованиеmyObject == MyDefine
не всегда будет работать должным образом, ноmyObject == MyStaticConst
будет.static NSString *const
а неstatic NSString const*
?? Какие-нибудь различия?static NSString const *
это то же самое, чтоstatic const NSString *
и означает «(изменяемый) указатель на константу NSString», что здесь немного бесполезно, поскольку NSString уже неизменна. То, что вы хотите толькоstatic NSString * const
- что является «постоянным указателем наFOUNDATION_EXPORT
Рассмотрите возможность использования
FOUNDATION_EXPORT
для большей совместимости, чемextern
это, поскольку она определена в фундаменте и компилируется в совместимые форматы для C, C ++ и Win32.Как определено в NSObjCRuntime.h
источник