我在理解苹果指南中定义的“测试类平等”的这一部分时遇到了问题。
在动态创建的子类中,通常会重写类方法,以便子类伪装成它所替换的类。因此,在测试类相等性时,应该比较类方法返回的值而不是低级函数返回的值。就API而言,以下不等式适用于动态子类:
[object class] != object_getClass(object) != *((Class*)object)
因此,您应该按如下方式测试两个类的相等性:
if ([objectA class] == [objectB class]) { //...
答案 0 :(得分:42)
在某些情况下,人们会在运行时添加新类。一个例子是Key Value Observing:当你观察一个对象时,Foundation框架会创建一个被观察对象类的新子类。此动态类的行为与其超类的行为相同,但将KVO通知添加到其所有mutator方法。
你引用的段落说,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 Untitled 2 [896:707]模型是NSObject, 观察者是一个NSObject
2012-06-08 08:37:26.907 Untitled 2 [896:707] model是NSKVONotifying_NSObject,observer是NSObject
2012-06-08 08:37:26.907 Untitled 2 [896:707]模型是NSKVONotifying_NSObject, 观察者是一个NSObject
正如文档所示,这只是第一种情况(我们比较-class
),它可以完成应用程序代码可以合理预期的任何事情。查找类的另外两种方法 - 询问运行时,并将对象指针强制转换为Class *
- 两者都提供了关于KVO如何从我们下面改变类的实现细节,并且意味着现在进行类比较不会表明班级是平等的。
由于其他答案和评论指的是-isMemberOfClass:
和-isKindOfClass:
,我也将涵盖这些观点:
-isKindOfClass:
不是一个类相等的测试。如果[object isKindOfClass: aClass]
是object
或其任何子类的实例,则aClass
为真。因为你引用的段落是关于阶级平等的,所以-isKindOfClass:
与此无关。也就是说,它通常是您希望在应用程序代码中进行的测试。关注“我可以将此对象用作Foo
”的答案更为常见吗?比“这个对象是Foo
的确切实例吗?”。
-isMemberOfClass:
是对类等式的测试:[object isMemberOfClass: aClass]
仅在对象是aClass
的实例时才为真。此测试是使用-class
方法的结果完成的,这意味着在此示例中,model
将为[model isMemberOfClass: [NSObject class]]
测试为正。
答案 1 :(得分:5)
应该是:
if([objctA isKindOfClass [MyClass class]])
答案 2 :(得分:1)
也许你可以使用&#39; NSStringFromClass&#39;方法并比较获得的字符串,感谢&#39; isEqualToString&#39; ?