Ответ 1
Есть ситуации, когда люди добавляют новые классы во время выполнения. Одним из примеров является наблюдение за ключевым значением: когда вы наблюдаете объект, Foundation Framework создает новый подкласс наблюдаемого класса объекта. Этот динамический класс ведет себя так же, как и его суперкласс, но добавляет KVO-уведомления ко всем его мутаторным методам.
В приведенном вами отрывке говорится, что среда выполнения Objective-C может отличить этот класс от исходного класса. Однако, поскольку это просто деталь реализации способа создания KVO, вы не должны знать и не заботиться об этом. Поэтому разработчики переопределили метод -class
своего нового класса, чтобы притворяться, что объекты все еще являются членами исходного класса.
Если вы хотите проверить, являются ли два объекта одного и того же класса, вы должны сравнить результаты своих методов -class
(которые принимают во внимание трюки, такие как KVO), вместо использования функций времени выполнения.
Вот пример:
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
int main(int argc, const char * argv[])
{
@autoreleasepool {
NSObject *observer = [NSObject new];
NSObject *model = [NSObject new];
[model addObserver: observer forKeyPath: @"count" options: 0 context: NULL];
//using -class methods:
NSLog(@"model is a %@, observer is a %@", [model class], [observer class]);
//casting to Class:
NSLog(@"model is a %@, observer is a %@", *(Class*)model, *(Class*)observer);
//using the runtime:
NSLog(@"model is a %@, observer is a %@", object_getClass(model), object_getClass(observer));
[model removeObserver: observer forKeyPath: @"count" context: NULL];
[model release];
[observer release];
}
return 0;
}
Вы видите, что все, что я делаю, это создание двух объектов, рассказывающих одному из них, чтобы наблюдать за другим, а затем выяснять, что представляют собой их классы. Вот результаты:
2012-06-08 08: 37: 26.904 Без названия 2 [896: 707] модель представляет собой NSObject, observer - это NSObject
2012-06-08 08: 37: 26.907 Без названия 2 [896: 707] модель является NSKVONotifying_NSObject, наблюдателем является NSObject
2012-06-08 08: 37: 26.907 Untitled 2 [896: 707] модель NSKVONotifying_NSObject, observer - это NSObject
Итак, как показывает документация, это только первый случай (где мы сравниваем -class
), который делает все, что мог бы ожидать код приложения. Два других способа узнать класс - задание времени выполнения и отбрасывание указателя на объект Class *
- обе выдают детали реализации того, как KVO изменил класс из-под нас, и означают, что сравнение классов теперь выиграло ' t показывают, что классы равны.
Поскольку другие ответы и комментарии относятся к -isMemberOfClass:
и -isKindOfClass:
, я также рассмотрю эти пункты:
-
-isKindOfClass:
не является критерием равенства классов.[object isKindOfClass: aClass]
истинно, еслиobject
является экземпляромaClass
или любого из его подклассов. Поскольку прохождение, которое вы процитировали, касается равенства классов,-isKindOfClass:
здесь не имеет значения. Тем не менее, это чаще всего тест, который вы хотите делать в коде приложения. Это чаще встречается в ответе на вопрос "могу ли я использовать этот объект какFoo
?"? чем "является ли этот объект экземпляром точно изFoo
?". -
-isMemberOfClass:
- это тест для равенства классов:[object isMemberOfClass: aClass]
является только true, если объект является экземпляромaClass
. Этот тест выполняется с использованием метода-class
, что означает, что в этом примереmodel
будет испытывать положительный результат для[model isMemberOfClass: [NSObject class]]
.