Распределять и инициализировать то, что они на самом деле делают
Может кто-нибудь объяснить мне, что init и alloc делают в Obj-C. Я читаю эту книгу obj-c, которая дает пример создания объекта, но на самом деле он не вникает в детали того, что он делает. Что возвращает alloc? что возвращает init?
Animal * k = [Animal alloc];
k = [k init];
Ответы
Ответ 1
-
alloc
выделяет кусок памяти для хранения объекта и возвращает указатель.
MyClass* myObj = [MyClass alloc];
myObj
пока не используется, поскольку его внутреннее состояние неправильно настроено. Итак, не пишите такой код.
-
init
устанавливает начальное условие объекта и возвращает его. Обратите внимание, что то, что возвращается [a init]
, может отличаться от a
. Это объясняет код Yannick:
-init{
self=[super init]; // 1.
if(self){ // 2.
....
}
return self; // 3.
}
- Сначала вам нужно вызвать суперкласс
init
, чтобы настроить переменные экземпляра суперкласса и т.д. Это может вернуть что-то, не равное оригиналу self
, поэтому вам нужно назначить то, что вернулось в self
.
- Если
self
не равно nil, это означает, что часть, управляемая суперклассом, была правильно инициализирована. Теперь вы выполняете свою инициализацию. Все переменные экземпляра устанавливаются на nil
(если он объект) и 0
, если он целочисленный. Вам нужно будет выполнить дополнительные начальные настройки.
- Верните настройки
self
. Возвращенный self
может отличаться от выделенного! Таким образом, вам нужно присвоить результат init
вашей переменной.
Это важный урок: никогда не разбивайте вызов на alloc
и init
. Не пишите:
MyClass* myObj = [MyClass alloc];
[myObj init];
потому что [myObj init]
может вернуть что-то еще. Не пытайтесь обойти это, написав:
MyClass* myObj = [MyClass alloc];
myObj=[myObj init];
потому что вы в конце концов забудете записать часть myObj=
во второй строке.
Всегда пишите:
MyClass* myObj = [[MyClass alloc] init];
Я также не рекомендую писать:
MyClass* myObj = [MyClass new];
потому что он неправильно вызывает метод инициализации: некоторые классы не принимают простой init
. Например, NSView
требуется initWithFrame:
, который нельзя вызвать с помощью new
. Поэтому не используйте new
.
Ответ 2
В простейшей форме:
-
alloc: short для распределения, резервирует местоположение памяти и возвращает указатель на эту ячейку памяти. Этот указатель затем сохраняется в переменной k.
-
init: короткий для инициализации, устанавливает объект и возвращает объект. Метод init зависит от объекта, но обычно он включает отправку сообщения init в суперкласс. И если этот метод init (суперкласса) возвращает объект (но не nil), некоторые ivars могут быть настроены в зависимости от задачи этого класса.
-
Пример реализации init, класс Schedule инициализирует свои каналы ivar с помощью пустого массива. В основном, вы предоставляете объект Schedule возможность самостоятельно сортировать, чтобы он мог начать получать сообщения после его создания. Вы можете удалить инициализацию каналов из метода init, но тогда вам нужно будет проверить, нет ли канала ivar в каждом методе класса Schedule и инициализировать его, если он действительно равен нулю.
- (Schedule*)init {
self = [super init];
if (self) {
channels = [[NSMutableArray alloc] initWithCapacity:0];
}
return self;
}
Ответ 3
alloc и init - два метода, которые унаследованы от NSObject
вы можете предоставить свои собственные методы или вызвать их из NSObject
alloc выделяет память для создания нового экземпляра вашего класса (@interface)
init инициализирует содержимое этого экземпляра, по умолчанию init устанавливает все значения элементов в 0/nil, но вы можете создать свой собственный метод init для настройки сделанного.
Animal * k = [[Animal alloc] init]; // creates a new Animal object
вы также можете написать
Animal * k = [Animal new]; // which would be a bit more similar to other languages
Ответ 4
Класс NSObject root предоставляет метод класса alloc
alloc: резервирует ячейку памяти и возвращает указатель на эту ячейку памяти.
Метод alloc имеет еще одну важную задачу, которая заключается в том, чтобы очистить память, выделенную для свойств объектов, установив их в ноль.
Это позволяет избежать обычной проблемы с памятью, содержащей мусор из того, что было ранее сохранено, но
недостаточно, чтобы полностью инициализировать объект.
Вам нужно объединить вызов alloc с вызовом init, другим методом NSObject:
- INIT
(ID);
Метод init используется классом, чтобы убедиться, что его свойства имеют соответствующие начальные значения при создании.
Правильный способ выделения и инициализации объекта состоит в том, чтобы вставить вызов alloc внутри вызова init, например:
ClassName * objectName = [ClassName alloc] init];
from: apple documents
Ответ 5
Alloc будет выделять память для объекта, но Init помещает объект в память и устанавливает значения по умолчанию.