#objective-c #oop #initialization #init #nsobject
#objective-c #ооп #инициализация #nsobject
Вопрос:
В Objective-C есть пара вещей, которые меня смущают:
Во-первых, в руководстве по objective-c очень ясно сказано, что каждый класс должен вызывать метод init своего подкласса. Немного неясно, должен ли класс, наследующий непосредственно от NSObject, вызывать свой init
метод. Так ли это? И если да, то почему это так?
Во-вторых, в разделе о NSObject есть это предупреждение:
Класс, которому не нужно наследовать какое-либо особое поведение от другого класса, тем не менее, должен быть сделан подклассом класса NSObject. Экземпляры класса должны, по крайней мере, обладать способностью вести себя как объекты Objective-C во время выполнения. Наследовать эту способность от класса NSObject намного проще и намного надежнее, чем заново изобретать ее в новом определении класса.
Означает ли это, что мне нужно указать, что все объекты наследуются от NSObject явно? Или это похоже на Java / Python / C #, где все классы являются подтипами NSObject? Если нет, есть ли какая-либо причина для создания корневого класса, отличного от NSObject?
Ответ №1:
1) Каждый раз, когда объект выделяется в Objective-C, его память обнуляется и должна быть инициализирована вызовом init
. Подклассы NSObject
могут иметь свои собственные специализированные init
подпрограммы, и в начале такой процедуры они должны вызывать init
подпрограмму своего суперкласса примерно так:
self = [super init];
Идея в том, что все init
подпрограммы в конечном итоге переходят к NSObject
s init
.
2) Вам нужно четко указать порядок наследования:
@instance myClass : NSObject { /*...*/ } @end
Нет причин иметь корневой класс, отличный от NSObject
— многие Objective-C сильно зависят от этого класса, поэтому попытка обойти его приведет к тому, что вы напрасно выстрелите себе в ногу.
Комментарии:
1. Как было отмечено в других сообщениях, иногда есть причина иметь другой корневой класс, чем NSObject. Cocoa включает дополнительный корневой класс NSProxy, который демонстрирует преимущества того, что NSObject является явным, а не неявным наследованием. Вы правы в том, что очень маловероятно, что сторонний разработчик должен создавать новый корневой класс.
Ответ №2:
Поскольку возможно наследование от разных корневых базовых классов, да, вы должны явно объявить, что вы наследуете от NSObject при создании любого нового класса (если, конечно, вы уже не создаете подкласс чему-то другому, который сам, в свою очередь, вероятно, является подклассом NSObject).
Почти никогда не возникает необходимости создавать свой собственный базовый класс, и это было бы непросто сделать.
Ответ №3:
Objective-C может иметь несколько корневых классов, поэтому вам нужно четко указать порядок наследования. IIRC NSProxy — это еще один корневой класс. Скорее всего, вы никогда не захотите или вам не понадобится создавать свой собственный корневой класс, но они существуют.
Что касается вызова инициализации NSObject, то это частично пользовательский, а частично безопасный способ. Инициализация NSObject может ничего не делать сейчас, это не гарантирует, что будущее поведение не изменится. Вызовите init для обеспечения безопасности.
Ответ №4:
Вам нужно вызвать [super init], потому что за инициализацией стоит код, который вам не нужно писать, потому что он написан для вас в NSObjects init, например, возможно, фактическое выделение памяти и т.д.
Комментарии:
1. Лакомый кусочек: некоторые классы Cocoa фактически наследуются от
NSProxy
, который является другим корневым классом в Cocoa framework. ОбаNSObject
иNSProxy
реализуютNSObject
протокол.