Когда вы ссылаетесь на self
в методе класса, self
относится к классу, а не к конкретному экземпляру этого класса. Используя self
, а не фактическое имя класса в этих методах класса, это облегчает подкласс класса, о котором идет речь. В частности, метод класса будет наследоваться, но ссылки self
теперь будут относиться к подклассу, а не к базовому классу. Если вы ссылаетесь на базовый класс по имени, это будет неверно.
Рассмотрим этот метод фабрики:
@implementation BaseClassObject
// THIS IS WRONG
+ (BaseClassObject *)object {
return [[BaseClassObject alloc] init];
}
@end
И рассмотрим этот подкласс:
@interface SubClassObject : BaseClassObject
@end
Затем рассмотрим код, который делает:
SubClassObject *object = [SubClassObject object]; // WRONG
Проблема заключается в том, что метод object
завод будет вернуть BaseClassObject
, а не SubClassObject
. Но это можно исправить, если изменить определение этого метода фабрики класса использовать self
:
@implementation BaseClassObject
// THIS IS RIGHT
+ (instancetype)object {
return [[self alloc] init];
}
@end
Теперь, когда я имею в виду [SubClassObject object]
, я получить экземпляр SubClassObject
, а не BaseClassObject
.
Примечание: В моем надуманный пример, это довольно важно использовать self
. Тем не менее, вы можете столкнуться с кодом, в котором он не кажется непосредственно актуальным (например, у вас может быть базовый класс, но в данный момент нет подкласса).
Даже в этом случае у вас, вероятно, должно быть привычное использование self
в этих методах класса, независимо от того, будет ли он «защищен будущим» вашим кодом, так что если вы когда-либо подклассифицируете этот базовый класс в какой-то непредвиденный срок в будущее, эти методы класса с большей вероятностью будут функционировать должным образом даже при подклассе.
Я не могу полностью согласиться с тем, что «это правильно» в последнем примере http://stackoverflow.com/a/26821507/2792531 – nhgrif
Я думаю, что наилучшая практика предполагает, что фактическая дополнительная конфигурация идет в методе init, и фабричный метод просто возвращает результат этого. – nhgrif
Дискуссия о том, что идет в фабричном методе и что идет в 'init', здесь не имеет особого значения, но я удалил эти комментарии для вас. – Rob