来看一道经典的面试题,猜猜下面程序输出结果是什么?
#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的不同点,先看看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;
}
还需要理解这张经典的图:
分析
- [(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
,所以循环会执行,比较tcls
和cls
,一个是NSObject元类,一个是NSObject,不相等,继续循环,这时tcls = tcls->superclass
,NSObject元类的父类是NSObject本身,所以tcls
变成了NSObject,比较tcls
和cls
,都是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
,所以循环会执行,比较tcls
和cls
,一个是XYStudent元类,一个是XYStudent,不相等,继续循环;
这时tcls = tcls->super_class
,XYStudent元类的父类是NSObject元类,于是tcls
变成了NSObject元类,再次比较tcls
和cls
,一个是NSObject元类,一个是XYStudent,不相等,继续循环;
这时又来到tcls = tcls->super_class
,tcls
是NSObject元类,NSObject元类的父类是NSObject,再次比较tcls
和cls
,一个是NSObject,一个是XYStudent,不相等,继续循环;
又来到tcls = tcls->super_class
,tcls
是NSObject,NSObject的父类是nil
,于是tcls
为nil
,循环结束,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
,进入循环,比较tcls
和cls
,均为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
,进入循环,比较tcls
和cls
,均为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
。