Переменные экземпляра, указанные в файле реализации ObjC

Я смотрел видеоролик вступления в WWDC ARC, и я видел то, чего я никогда не видел в ObjC, прежде чем кто-то из инженеров Apple говорил о примере Stack.

Следующий код использовался для примера стека с ARC:

@implementation Stack 
{ 
    // instance variable declared in implementation context
    NSMutableArray *_array; 
}

- (id)init 
{
   if (self = [super init])
      _array = [NSMutableArray array];
   return self;
}

- (void)push:(id)x 
{
   [_array addObject:x];
}

- (id)pop 
{
   id x = [_array lastObject];
   [_array removeLastObject];
   return x;
}

@end

Обратите внимание на переменную экземпляра, объявленную сразу после директивы @implementation.

Теперь то, что меня удивило, заключается в том, что переменная экземпляра действительно может быть объявлена ​​в файле реализации, без статической переменной. Мои вопросы будут следующими:

  • Это какая-то новая конструкция, введенная в SDK для iOS 5, или это возможно в течение длительного времени?
  • Было бы хорошей практикой объявлять переменные экземпляра в реализации, если переменные экземпляра не должны быть доступны за пределами объекта? Кажется, это чище, чем использование директивы @private.

Ответ 1

Это действительно новая языковая функция, и если вы должны объявить свои ivars (а не просто объявлять свойства и позволить компилятору генерировать ivars для вас), это хорошая практика. Ваши файлы заголовков в теории должны выставлять публичный интерфейс для ваших классов; все остальное принадлежит реализации.

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

Ответ 2

Объявление iVars внутри реализации является, безусловно, новой конструкцией в объекте C. Вы должны использовать xcode4.2 и иметь компилятор LLVM, выбранный в настройках сборки. Идея состоит в том, чтобы очистить файлы заголовков. Вы можете перечислить свои ivars внутри фигурных скобок как этот пример;

@implementation MyClass {    
  int var1;
  int var2;
}

Ответ, данный Рахулом, не совсем правильный, хотя вы можете делиться переменными так, как он говорит, что их компилятор будет рассматривать как статический. Вероятно, для случаев, когда он их использовал, это не имело значения.

Ответ 3

Я новичок в Objective C, и я нашел, что практика объявления ivars в заголовке очень странная. Это означает объявление внутреннего состояния объекта в его публичном заголовке, что противоречит концепции инкапсуляции.

Например, у вас есть IPad. Apple не хочет, чтобы вы нарушали IPad, открывали и подглядывали, и возились с элементами внутри. Если они хотят, чтобы вы что-то изменили, у IPad будет параметр, который позволит вам изменить это.

Точно так же я не хочу, чтобы другие программисты видели ivars моих объектов. Его внутреннее состояние моего объекта. Если я хочу, чтобы вы достигли внутреннего состояния, я объявлю для него свойства.

Итак, как и в других языках, я бы спрятал свои ivars внутри файла реализации и не объявлял их в заголовке.

Объявление ivars в заголовке просто поражает меня очень странно. Эти ivars являются специфичными для реализации и не должны просто быть частью файла заголовка.