Objective-C: Должны ли методы инициализации объявляться в .h?

Во-первых, насколько я понимаю, init в Objective-C функционально аналогичен конструктору в Java, так как он используется для инициализации переменных экземпляра и подготовки класса к какой-то работе. Это правильно?

Я понимаю, что NSObject реализует init и поэтому его не нужно объявлять ни в каких .h файлах.

Но как насчет пользовательской реализации init для данного класса, например:

(id) initWithName:(NSString *) name

Должна ли подобная декларация быть указана как часть .h, или это не обязательно? Это сделано по соглашению или есть другие причины?


person James Raitsev    schedule 19.07.2011    source источник


Ответы (2)


init никоим образом не похож на конструктор в Java/C++. Конструктор всегда выполняется при создании объекта. Но исполнение init зависит от вас. Если вы не отправите сообщение init после alloc, оно не будет выполнено.

// init does not execute here
MyObject *obj = [MyObject alloc];

И это будет работать без проблем, если вы наследуете от NSObject, так как init из NSObject ничего не делает.

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

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

person taskinoor    schedule 19.07.2011
comment
Спасибо. Если я инициализирую свой класс с помощью пользовательского метода инициализации, значит ли это, что я всегда должен [super init], чтобы убедиться, что инициализация NSObjet вызывается хотя бы один раз? - person James Raitsev; 19.07.2011
comment
Да, вы должны делать это всегда, даже если инициализация NSObject не выполняет инициализацию. Это хорошая практика, и нет никаких проблем, когда вы вызываете это. И для большинства других классов, вызывающих суперкласс, требуется инициализация. Итак, итог: всегда вызывайте метод инициализации базового класса. - person taskinoor; 19.07.2011
comment
Я не уверен, почему я получил отрицательный голос здесь. Комментарий, объясняющий мою ошибку, помог бы мне. - person taskinoor; 27.02.2013

Да, вы должны объявить его, если хотите иметь возможность вызывать этот персонализированный метод инициализации (initWithName). И первое, что вам нужно сделать в этом методе, это вызвать [super init];.

person Pierre Watelet    schedule 19.07.2011
comment
Было бы лучше сказать, что инициализатор должен вызывать назначенный инициализатор своего суперкласса. Назначенный инициализатор не обязательно -init, и вы можете выполнять другую работу перед вызовом назначенного инициализатора. - person Caleb; 19.07.2011
comment
Вы не должны обязаны заявлять об этом. Его по-прежнему можно будет вызывать без объявления, но вы получите предупреждения компилятора при попытке использовать его из других классов. - person Richard; 19.07.2011