Чтобы понять это, вероятно, важно понять, как объект хранится во время выполнения.Существует объект класса 1 , который содержит все реализации метода, и отдельно существует структура с хранилищем для переменных экземпляра.Все экземпляры класса совместно используют один объект класса.
Когда вы вызываете метод в экземпляре, компилятор превращает это в вызов objc_msgSend
;реализация метода ищется в объекте класса, а затем запускается с экземпляром в качестве аргумента.
Ссылка на super
вступает в силу во время компиляции, не во время выполнения.Когда вы пишете [super someMethod]
, компилятор превращает это в вызов objc_msgSendSuper
вместо обычного objc_msgSend
.Это начинает искать реализацию метода в объекте класса суперкласса , а не в объекте класса экземпляра. 2
Категория просто добавляет методы к объекту класса;он почти не имеет отношения к подклассам.
Учитывая все это, если вы ссылаетесь на super
внутри категории, он действительно делает то же самое, что и внутри класса, - реализацию метода.ищется на объекте класса суперкласса , а затем запускается с этим экземпляром в качестве аргумента.
Пост Итая отвечает на вопрос более прямо, но в коде:
@interface Sooper : NSObject {}
- (void) meth;
@end
@interface Sooper ()
- (void) catMeth;
@end
@interface Subb : Sooper {}
- (void) subbMeth;
@end
@interface Subb ()
- (void) catSubbMeth;
@end
@implementation Sooper
- (void) meth {
[super doIt]; // Looks up doIt in NSObject class object
}
- (void) catMeth {
[super doIt]; // Looks up doIt in NSObject class object
}
@end
@implementation Subb
- (void) subbMeth {
[super doIt]; // Looks up doIt in Sooper class object
}
- (void) catSubbMeth {
[super doIt]; // Looks up doIt in Sooper class object
}
@end
1 См. Реферат Грега Паркера [Объяснение объекта]: Классы и мета-классы
2 Одна важная вещьСледует отметить, что метод не вызывается на экземпляре суперкласса.Вот где происходит это разделение методов и данных. Метод по-прежнему вызывается в том же экземпляре, в котором было написано [super someMethod]
, то есть в экземпляре подкласса, используя данные этого экземпляра;он просто использует реализацию метода суперкласса.
Таким образом, вызов [super class]
переходит к объекту суперкласса, находит реализацию метода с именем class
и вызывает его в экземпляре, превращая его в эквивалент [self theSuperclassImplementationOfTheMethodNamedClass]
.Поскольку все, что делает этот метод, - это возвращает класс экземпляра , для которого он был назван , вы не получаете класс суперкласса, вы получаете класс self
.В связи с этим, вызов class
является плохой проверкой этого явления.
Весь этот ответ полностью игнорирует различие между передачей сообщений / вызовом метода.Это важная особенность ObjC, но я думаю, что это, вероятно, будет просто грязным и без того неловким объяснением.