isKindOfClass isMemberOfClass

以下的代码会输出什么结果?

@interface Sark : NSObject
@end
@implementation Sark
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...

        NSLog(@"%@", [NSObject class]);
        NSLog(@"%@", [Sark class]);

        BOOL res1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];
        BOOL res2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]];
        BOOL res3 = [(id)[Sark class] isKindOfClass:[Sark class]];
        BOOL res4 = [(id)[Sark class] isMemberOfClass:[Sark class]];
        NSLog(@"%d--%d--%d--%d", res1, res2, res3, res4);
    }
    return 0;
}

结果: 1--0--0--0

分析:

首先,我们先去查看一下题干中两个方法的源码:

- (BOOL)isMemberOfClass:(Class)cls {
    return [self class] == cls;
}

- (BOOL)isKindOfClass:(Class)cls {
    for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
        if (tcls == cls) return YES;
    }
    return NO;
}

可以得知:

  • isKindOfClass 的执行过程是拿到自己的 isa 指针和自己比较,若不等则继续取 isa 指针所指的 super class 进行比较。如此循环。
  • isMemberOfClass 是拿到自己的 isa 指针和自己比较,是否相等。

  • NSObject class 执行完之后调用 isKindOfClass,第一次判断先判断 NSObject 和 NSObject 的 meta class 是否相等,之前讲到 meta class 的时候放了一张很详细的图,从图上我们也可以看出,NSObject 的 meta class 与本身不等。接着第二次循环判断 NSObject 与meta class 的 superclass 是否相等。还是从那张图上面我们可以看到:Root class(meta) 的 superclass 就是 Root class(class),也就是 NSObject 本身。所以第二次循环相等,于是第一行 res1 输出应该为YES。

  • isa 指向 NSObject 的 Meta Class,所以和 NSObject Class不相等。
  • Sark class 执行完之后调用 isKindOfClass,第一次 for 循环,Sark 的 Meta Class 与 Sark class 不等,第二次 for 循环,Sark Meta Class 的 super class 指向的是 NSObject Meta Class, 和 Sark Class 不相等。第三次 for 循环,NSObject Meta Class 的 super class 指向的是 NSObject Class,和 Sark Class 不相等。第四次循环,NSObject Class 的super class 指向 nil, 和 Sark Class 不相等。第四次循环之后,退出循环,所以第三行的 res3 输出为 NO。
  • isa 指向 Sark 的 Meta Class,和 Sark Class 也不等。

Reference

Runtime学习:面试题狙击

results matching ""

    No results matching ""