isKindOfClass和isMemberOfClass

来看一道经典的面试题,猜猜下面程序输出结果是什么?

#import 
#import "XYStudent.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        BOOL re1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];
        BOOL re2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]];
        BOOL re3 = [(id)[XYStudent class] isKindOfClass:[XYStudent class]];
        BOOL re4 = [(id)[XYStudent class] isMemberOfClass:[XYStudent class]];
        NSLog(@"\nre1: %hhd\nre2: %hhd\nre3: %hhd\nre4: %hhd\n",re1, re2, re3, re4);

        BOOL re5 = [(id)[NSObject alloc] isKindOfClass:[NSObject class]];
        BOOL re6 = [(id)[NSObject alloc] isMemberOfClass:[NSObject class]];
        BOOL re7 = [(id)[XYStudent alloc] isKindOfClass:[XYStudent class]];
        BOOL re8 = [(id)[XYStudent alloc] isMemberOfClass:[XYStudent class]];
        NSLog(@"\nre1: %hhd\nre2: %hhd\nre3: %hhd\nre4: %hhd\n",re5, re6, re7, re8);
        
    }
    return 0;
}

先说答案,输出如下:


isKindOfClass和isMemberOfClass_第1张图片
输出

这里需要明白isKindOfClass和isMemberOfClass的不同点,先看看runtime中的源码:

+ (BOOL)isMemberOfClass:(Class)cls {
    return object_getClass((id)self) == cls;
}

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

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

还需要理解这张经典的图:


isKindOfClass和isMemberOfClass_第2张图片

分析

  • [(id)[NSObject class] isKindOfClass:[NSObject class]];
    NSObject是一个类对象,类对象发送class消息的时候,返回的是自身,也就是类对象本身,所以返回的还是NSObject,这时会执行类方法:
+ (BOOL)isKindOfClass:(Class)cls {
    for (Class tcls = object_getClass((id)self); tcls; tcls = tcls->super_class) {
        if(tcls == cls) return YES;
    }
    return NO;
}

Class tcls = object_getClass((id)self)执行后,tcls是NSObject元类,又由于tcls不是nil,所以循环会执行,比较tclscls,一个是NSObject元类,一个是NSObject,不相等,继续循环,这时tcls = tcls->superclass,NSObject元类的父类是NSObject本身,所以tcls变成了NSObject,比较tclscls,都是NSObject,相等,return YES,所以re1 = 1

  • [(id)[NSObject class] isMemberOfClass:[NSObject class]]
    同样,NSObject是一个类对象,类对象发送class消息的时候,返回的是自身,也就是类对象本身,所以返回的还是NSObject,这时会执行类方法:
+ (BOOL)isMemberOfClass:(Class)cls {
    return object_getClass((id)self) == cls;
}

object_getClass((id)self)返回的是NSObject元类,而cls是NSObject本身,不相等,return NO,所以re2 = 0

  • [(id)[XYStudent class] isKindOfClass:[XYStudent class]]
    同样,XYStudent是一个类对象,类对象发送class消息的时候,返回的是自身,也就是类对象本身,所以返回的还是XYStudent,这时会执行类方法:
+ (BOOL)isKindOfClass:(Class)cls {
    for (Class tcls = object_getClass((id)self); tcls; tcls = tcls->super_class) {
        if(tcls == cls) return YES;
    }
    return NO;
}

首先Class tcls = object_getClass((id)self)tcls是XYStudent元类,又由于tcls不是nil,所以循环会执行,比较tclscls,一个是XYStudent元类,一个是XYStudent,不相等,继续循环;
这时tcls = tcls->super_class,XYStudent元类的父类是NSObject元类,于是tcls变成了NSObject元类,再次比较tclscls,一个是NSObject元类,一个是XYStudent,不相等,继续循环;
这时又来到tcls = tcls->super_classtcls是NSObject元类,NSObject元类的父类是NSObject,再次比较tclscls,一个是NSObject,一个是XYStudent,不相等,继续循环;
又来到tcls = tcls->super_classtcls是NSObject,NSObject的父类是nil,于是tclsnil,循环结束,return NO,所以re3 = 0

  • [(id)[XYStudent class] isMemberOfClass:[XYStudent class]]
    同样,XYStudent是一个类对象,类对象发送class消息的时候,返回的是自身,也就是类对象本身,所以返回的还是XYStudent,这时会执行类方法:
+ (BOOL)isMemberOfClass:(Class)cls {
    return object_getClass((id)self) == cls;
}

object_getClass((id)self)返回的是NSObject元类,而cls是XYStudent,不相等,return NO,所以re4 = 0

  • [(id)[NSObject alloc] isKindOfClass:[NSObject class]]
    [NSObject alloc]返回的是NSObject的对象,所以调用对象方法:
-(BOOL)isKindOfClass:(Class)cls {
    for(Class tcls = [self class]; tcls; tcls = tcls->super_class) {
        if(tcls == cls) return YES;
    }
    return NO;
}

Class tcls = [self class]tcls为NSObject,由于tcls不为nil,进入循环,比较tclscls,均为NSObject,return YES,所以re5 = 1

  • [(id)[NSObject alloc] isMemberOfClass:[NSObject class]]
    同样,[NSObject alloc]返回的是NSObject的对象,所以调用对象方法:
- (BOOL)isMemberOfClass:(Class)cls {
    return [self class] == cls;
}

[self class]返回NSObject,cls也是NSObject,return YES,所以re6= 1

  • [(id)[XYStudent alloc] isKindOfClass:[XYStudent class]]
    [XYStudent alloc]返回的是XYStudent的对象,所以调用对象方法:
-(BOOL)isKindOfClass:(Class)cls {
    for(Class tcls = [self class]; tcls; tcls = tcls->super_class) {
        if(tcls == cls) return YES;
    }
    return NO;
}

Class tcls = [self class]tcls为XYStudent,由于tcls不为nil,进入循环,比较tclscls,均为XYStudent,return YES,所以re7 = 1

  • [(id)[XYStudent alloc] isMemberOfClass:[XYStudent class]]
    同样,[XYStudent alloc]返回的是XYStudent的对象,所以调用对象方法:
- (BOOL)isMemberOfClass:(Class)cls {
    return [self class] == cls;
}

[self class]返回XYStudent,cls也是XYStudent,return YES,所以re8 = 1

你可能感兴趣的:(isKindOfClass和isMemberOfClass)