Почему в Objective-C мы используем self = [super init] вместо просто [super init]?
В книге я увидел, что если подкласс переопределяет метод суперкласса, мы можем иметь
self = [super init];
Во-первых, предполагается ли это в методе подкласса init
?
Во-вторых, мне интересно, почему вызов не просто
[super init];
? Я имею в виду, что во время вызова init
память выделяется alloc
уже (я думаю, [Foobar alloc]
, где Foobar
- это имя подкласса. Поэтому мы не можем просто вызвать [super init]
для инициализации переменные-члены? Почему мы должны получить возвращаемое значение init
и присваивать self
? Я имею в виду, что перед вызовом [super init]
, self
должен указывать на допустимый патч памяти... так зачем присваивать что-то для себя снова?
(если назначить, не будет [super init]
просто вернуть self
существующее значение?)
Ответы
Ответ 1
Итак, зачем присваивать значение, возвращенному из [super init], самому себе? Смотря на типичный метод инициализации:
- (id)initWithString:(NSString *)aString {
self = [super init];
if (self)
{
instanceString = [aString retain];
}
return self; }
Почему мы назначаем [super init] для себя здесь?
Причина учебника заключается в том, что [super init] разрешено выполнять одну из три вещи:
- Вернуть собственный ресивер (указатель не изменяется) с помощью инициализируются значения унаследованных экземпляров.
- Возвращает другой объект с инициализируются значения унаследованных экземпляров.
- Возвращает нуль, указывая на сбой.
В первом случае присваивание не влияет на self и instanceString устанавливается в исходном объекте (строка instanceString = [aString сохранить]; может быть первой линией метод и результат будут одинаковыми).
В третьем случае инициализация завершилась неудачно. self устанавливается в nil, никаких дальнейших действий не предпринимается, и возвращается nil.
Обоснование присвоения себе связано со вторым case: если возвращаемый объект отличается, мы хотим:
instanceString = [aString retain]; which gets converted to
self->instanceString = [aString retain]; to act on the correct value,
поэтому мы должны изменить значение self, чтобы указать на этот новый объект.
надеясь, что это поможет...
От Cocoa с любовью
Ответ 2
Классическим примером возврата другого объекта из -init
является реализация кластера классов - абстрактного интерфейса с несколькими конкретными исполнителями, обеспечивающих различное хранилище или алгоритмы. +[NSString alloc]
возвращает экземпляр NSPlaceholderString
. Инициализаторы экземпляра-заполнителя проверяют их параметры, освобождают строку-заполнитель и возвращают инициализированный экземпляр конкретного подкласса NSString
.
Ответ 3
Возможно, суперкласс может решить, что объект не может быть инициализирован должным образом и возвращает nil как отказ. Если вы не назначаете nil для себя, ваш метод init будет продолжаться в предположении, что родительский класс правильно инициализировал объект.
Также возможно, чтобы родительский класс также возвращал совершенно другой объект, если он хочет.
Ответ 4
Поймите, что объект уже выделен и само указывает на память.
Теперь [super init] выполняет инициализацию.
1) Если инициализация является успешной самооценкой одного объекта перед инициализацией
2) Если инициализация - это отказ, функция init возвращает nil и self = nil. Теперь мы можем проверить, инициализирован ли объект, и если да, сделаем нашу магию с помощью этого кода
if(self = [super init]){
// do our magic
}
IT так же, как мы используем imageView, мы обычно используем
UIImageView imgView = [[UIImageView alloc] init];
imgView будет иметь только значение nil, если оба параметра alloc и init будут успешными.