Разница между объявлением ivar в @interface и помещением переменной в @implementation

В чем разница между объявлением ivar в @interface и помещением переменной в @implementation в файле .m?

@interface MyClass : NSObject {
  int num;
}
- (void)doSomething;
@end

vs.

@implementation MyClass   
int num2;

- (void)doSomething {
  num = 137;
  num2 = 138;
}
@end

Бывает ли такое, что вы хотите поместить переменную в @implementation?


person nickfox    schedule 06.04.2011    source источник


Ответы (3)


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

Вариант использования для определения его в области файла — это хранить вещи для статических методов (методов, которые действуют непосредственно на класс, а не на экземпляр класса). Действительно распространенным вариантом использования для этого является шаблон проектирования Singleton. Вы можете определить статический экземпляр вашего класса в этом файле, чтобы в любое время убедиться, что вы обращаетесь к одному и тому же экземпляру. Вы можете предоставить статический метод, который возвращает этот экземпляр, чтобы любой объект в вашем коде мог получить доступ к тому же объекту, вызвав метод непосредственно в вашем классе.

Обновление от 17.04.14

Общепринятой практикой сейчас является использование Свойства . Это создает геттеры и сеттеры для вас, автоматически делая класс более расширяемым (если вы решите изменить способ работы свойства, возможно, вы хотите изменить его, чтобы он всегда вычислялся на лету, общедоступный интерфейс класса не нужно менять ).

Вы можете использовать частные расширения класса для объявления "частных" свойств и методов. Это приводит к защите определенных свойств и методов от доступа к внешним классам.

person drewag    schedule 06.04.2011
comment
Очень хорошим объяснением может быть следующее: переменная класса определена в @implementation, а не в @interface? - person rohan-patel; 29.03.2013
comment
Этот ответ немного устарел. Теперь намного лучше помещать ивары в @implementation, но не забудьте использовать фигурные скобки. Если в фигурных скобках, переменные будут переменными экземпляра. Без фигурных скобок переменные будут глобальными переменными. - person rmaddy; 17.04.2014
comment
гораздо лучше - это преувеличение. Я бы сказал, что вы хотите поместить его в файл реализации всякий раз, когда это переменная, с которой другие классы не должны связываться. Однако сейчас обычно предпочтительнее использовать свойства. Вы можете использовать расширения частного класса для объявления частных свойств и методов. - person drewag; 17.04.2014
comment
но спасибо, что указали, что ответ несколько устарел. Я предоставил обновление для его модернизации. - person drewag; 17.04.2014

Насколько я знаю, размещение объявления переменной внутри @implementation ничем не отличается от помещения его вне реализации: это не ivar, это просто переменная, объявленная в области файла.

Одно из применений — объявление эквивалента статических членов C++. Например:

@implementation MyClass

static int s_count = 0;

- (id)init {
  if ((self = [super init]))
    ++s_count;
  return self;
}

- (void)dealloc {
  --s_count;
  [super dealloc];
}

Предполагая, что init является вашим единственным инициализатором, тогда s_count будет содержать общее количество активных экземпляров MyClass.

person Tony    schedule 06.04.2011
comment
То есть статические глобальные переменные могут использоваться как переменные класса. - person ; 06.04.2011
comment
Я только что разговаривал об этом с некоторыми людьми, и они сказали, что ivar является переменной экземпляра, в то время как переменная, объявленная в @implementation, является глобальной, а не для каждого экземпляра. Для меня это звучит как статика. Я понимаю, что такое ivar, но все еще не понимаю переменную в @implementation и когда ее следует использовать. - person nickfox; 06.04.2011
comment
@nickfox Глобальные переменные, статические или нет, имеют то же время жизни, что и программа, и могут использоваться любым методом или функцией в файле реализации, поэтому их можно использовать как переменные класса. Нестатическая глобальная переменная также может использоваться другими файлами реализации, подобно общедоступной переменной класса. статическая глобальная переменная может использоваться только файлом реализации, в котором она объявлена, поэтому она действует как частная переменная класса. - person ; 06.04.2011

Примечание. Исторически интерфейс требовал объявления переменных экземпляра класса, структур данных, которые являются частью каждого экземпляра класса. Они были объявлены в фигурных скобках после объявления @interface и перед объявлениями методов:

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

(источник)

person unknownwill    schedule 05.08.2012