Зачем использовать [ClassName alloc] вместо [[self class] alloc]? - PullRequest
17 голосов
/ 24 августа 2010

Я читаю книгу Марка Далримпла Learn Objective-C на Mac (только в главе, посвященной протоколам, так что все еще относительно новичок) и пытаюсь что-то выяснить:Вы бы когда-нибудь ссылались на класс под собственным именем?Если бы у меня был класс с именем Foo, зачем мне писать, скажем,

[[Foo alloc] init]

, а не

[[[self class] alloc] init]

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

[[Bar alloc] init]

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

Ответы [ 3 ]

26 голосов
/ 24 августа 2010

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

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

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

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

6 голосов
/ 24 августа 2010

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

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

0 голосов
/ 03 октября 2015

Я обнаружил условие, при котором [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].Вероятно, это просто компилятор, который не может устранить неоднозначность, хотя контекст кажется достаточно ясным.

...