Эквивалент открытых статических конечных переменных


Я понимаю, что размещение слова extern Перед объявлением переменной в заголовочном файле объявляет о существовании глобальной статической переменной без ее инициализации. Я также понимаю, что если я импортирую файл, содержащий переменные extern, я могу ссылаться на них без имени класса / файла. Но как определить их и их ценности?

То, что я пытаюсь сделать, - это создать класс констант с глобальными константами, которые я хочу использовать в приложении iOS. код.

Можно ли поместить их в интерфейс вот так?

Пример.h

#import <Foundation/Foundation.h>
@interface Constraints : NSObject
{

extern   NSString * const PREFS_NAME;

}

Или кто-то ставит тогда вне интерфейса, как это

Пример.h

#import <Foundation/Foundation.h>

extern   NSString * const PREFS_NAME;    

@interface Constraints : NSObject
{

}

Затем в реализации .m file как инициализировать значения extern?

Внутри такой области реализации?

Пример.m

#import "Constraints.h"

@implementation Constraints

/**PRefecences name for the application**/
const  NSString * PREFS_NAME = @"MyApp_Prefs";

@end

Или инициализировать их вне области реализации, как это:

Пример.m

#import "Constraints.h"

/**PRefecences name for the application**/
const  NSString * PREFS_NAME = @"MyApp_Prefs";

@implementation Constraints

@end

Или я предоставляю им их начальные значения в конструкторе? или какой-то произвольный метод статического стиля с + перед ним, т. е. +(void) setAppConstraints;

Я пробовал несколько комбинаций, но всегда сталкивался с ошибками, такими как"переопределение 'xVariable' с другим типом". Или что-то вроде "extern не имеет интерфейса инициализации" (или что-то в этом роде, я забыл). Поэтому я хочу знать, как декларировать и инициализировать их правильно сформировать ту же роль, что и переменные public static final в Java.

Также каковы пределы команды extern? Я знаю, что могу extern an NSInteger или NSString, но как насчет NSArray?

Я задаю этот вопрос, потому что, по-видимому, существует много вводящей в заблуждение или неполной информации относительно использования extern в Objective-C. Многие ответы кажутся спекулятивными. Я надеюсь, что этот вопрос будет хорошим ресурсом не только для меня, но и для ограничения дальнейших подобных вопросов об основах из extern.
2 7

2 ответа:

Вы определяете его значение в файле, внутри которого он объявлен, что в вашем случае является примером.m; вы все еще можете повторно назначить эту переменную, поэтому объявление в Примере.h будет выглядеть так:

extern  NSString * PREFS_NAME;

Таким образом, каждый файл, который импортирует пример.h имеет доступ к этой переменной. Эквивалент общедоступные статические заключительные в Objective-C является константной. Если вы также хотите, чтобы он был общедоступным, вы должны сделать его переменной экземпляра класса, но в этом случае он вам не нужен, потому что он уже доступен везде. Так что в данном случае это будет:

// .m file
NSString* const PREFS_NAME = @"MyApp_Prefs";
// .h file
extern NSString* const PREFS_NAME;

Также обратите внимание, что const NSString * отличается от NSString* const. Последний является указателем const на NSString. Первый не имеет смысла, даже если это правильный синтаксис. В Objective-C классификатор const не влияет на объекты, вместо этого существуют изменяемые и неизменяемые классы. Это имело бы смысл в C++, что означает, что вы можете использовать только методы const на экземпляре.

extern используется для передачи компилятору сигнала о том, что вы будете использовать переменную или функцию, определенную в другом блоке компиляции.

Когда вы говорите extern const NSString *PREFS_NAME, Вы говорите: "замените все ссылки в этом блоке компиляции на PREFS_NAME на переменную PREFS_NAME, как она определена в другом файле."Поэтому, когда вы пытаетесь назначить PREFS_NAME в вашем .м, все, что вы делаете, это пытаетесь назначить переменную, которая, хотя и имеет имя, не существует. Объявление переменной extern является только объявление переменной или функции, а неопределение этой переменной или функции. Это позволяет компилятору знать, что имя используется, и что компоновщик позаботится о том, что с ним делать, но даже если вы предоставляете тип здесь, он на самом деле не выделяет пространство для переменной, он ожидает, что пространство будет выделено в блоке компиляции, который фактически определяет переменную.

Вы компилируете три или четыре разных файла исходного кода вместе, три из которых они могут заявить:

extern int buffer[];

И можно объявить

int buffer[BUFSIZE];

В своей глобальной области, и задача компоновщика состоит в том, чтобы разрешить три объявленные ссылки на extern buffer к фактическому определению буфера четвертого.

extern это для переменных и функций C так же, как @class для классов Objective-C, это прямое объявление, обещание компилятору, что вам не нужно волноваться, когда вы видите имя, которое здесь не определено, потому что компоновщик ответит на все, что угодно возможно, у вас есть какие-то нерешенные вопросы.