Подтвердить что ты не робот

Зачем использовать [ClassName alloc] вместо [[self class] alloc]?

Я читаю Mark Dalrymple Learn Objective-C на Mac (только в главе о протоколах, так что все еще относительно новичок) и пытаюсь понять что-то:

Зачем вам когда-либо ссылаться на класс по его собственному имени? Если бы у меня был класс под названием Foo, зачем мне когда-либо писать, скажем,

[[Foo alloc] init]

а не

[[[self class] alloc] init]

Если бы у меня была панель подкласса, не первый вариант лишил меня возможности писать

[[Bar alloc] init]

тогда как второй вариант позволит это? Когда первый вариант будет лучше?

4b9b3361

Ответ 1

Как правило, в методе класса вы используете [[self alloc] init]. Например, канонический способ написать метод удобства для класса:

+ (id)fooWithBar:(Bar *)aBar
{
    return [[[self alloc] initWithBar:aBar] autorelease];
}

(Обратите внимание, что в методе класса self относится к объекту класса.)

Однако вы бы использовали [[Foo alloc] init] (то есть явное имя класса), если вам действительно нужен экземпляр класса Foo (а не подкласс).

Ответ 2

Вы ссылаетесь на класс по его имени всякий раз, когда хотите именно этот класс. Если подкласс был получен из этого класса, то сам в том же методе вместо этого будет представлять этот производный класс. Следовательно, если вы хотите явно создать экземпляр суперкласса, это можно сделать.

Бывают случаи, когда это может иметь смысл. Либо заставить подкласс переопределить метод, чтобы вернуть экземпляр класса. Или вернуть другой класс, например, объект-заполнитель, используемый при создании NSArray и т.д.

Ответ 3

Я нашел условие, при котором [ClassName alloc] и [self alloc] не были эквивалентными. Я перечисляю его, если другие сталкиваются с подобной ситуацией.

//Option 1 
+ (NSInputStream *)streamWBlockWithArray:(NSArray *)dataArray 
{ return [[[self alloc] initWithArray:dataArray] autorelease]; } 
// Option 2 
+ (NSInputStream *)streamBlockWithArray:(NSArray *)dataArray
{ return [[[Block alloc] initWithArray:dataArray] autorelease]; }

Если я использую параметр 1, компилятор выдавал ошибку компилятора для дублированных определений, определение initWithArray помечено как противоречащее определению из + [NSArray initWithArray]. Ошибка компилятора исчезла после того, как я заменил [self alloc] на [Block alloc]. Вероятно, это просто компилятор, который не может устранить неоднозначность, хотя контекст кажется достаточно ясным.