Objective-c中的"测试类平等"

S.J*_*S.J 29 iphone objective-c ios

我在理解苹果指南中定义的"测试类平等"的这一部分时遇到了问题.

在动态创建的子类中,通常会重写类方法,以便子类伪装成它所替换的类.因此,在测试类相等性时,应该比较类方法返回的值而不是低级函数返回的值.就API而言,以下不等式适用于动态子类:

[object class] != object_getClass(object) != *((Class*)object)
Run Code Online (Sandbox Code Playgroud)

因此,您应该测试两个类的相等性,如下所示:

if ([objectA class] == [objectB class]) { //...
Run Code Online (Sandbox Code Playgroud)

小智 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;
}
Run Code Online (Sandbox Code Playgroud)

你看到我正在做的就是创建两个对象,告诉其中一个对象,然后找出他们的类是什么.结果如下:

2012-06-08 08:37:26.904 Untitled 2 [896:707]模型是NSObject,观察者是NSObject

2012-06-08 08:37:26.907 Untitled 2 [896:707]模型是NSKVONotifying_NSObject,观察者是NSObject

2012-06-08 08:37:26.907 Untitled 2 [896:707]模型是NSKVONotifying_NSObject,观察者是NSObject

因此,正如文档所示,它只是第一种情况(我们比较的地方-class),它可以完成应用程序代码可以合理预期的任何事情.找到类的另外两种方法 - 询问运行时,并将对象指针转换为Class *- 都会给出关于KVO如何从我们下面改变类的实现细节,并且意味着类比较现在不会显示班级是平等的.

因为其他的答案和评论指的是-isMemberOfClass:-isKindOfClass:,我将介绍这些点太:

  • -isKindOfClass:不是类平等的测试.[object isKindOfClass: aClass]如果objectaClass 其子类的实例或任何子类,则为true .因为你引用的段落是关于阶级平等的,-isKindOfClass:所以这里不相关.也就是说,它通常是您希望在应用程序代码中进行的测试.关注"我可以将此对象用作Foo?" 的答案更为常见.比"这个对象究竟是一个实例Foo吗?".

  • -isMemberOfClass:是对类相等性的测试:[object isMemberOfClass: aClass]仅当object是实例时才是真的aClass.该测试使用该-class方法的结果完成,这意味着在该示例model 中将测试为正[model isMemberOfClass: [NSObject class]].