由下方代码可知,isKindOfClass()确定一个对象是否是这个类的成员,或者有派生类,isMemberOfClass()只能确定对象是否是当前类的成员
re1和re3是判断当前类的指针是否指向它自己
re2和re4是判断当前类是否是它自己
congoing打印结果可以看出,
直接源码查找isKindOfClass()方法发现
+isKindOfClass()方法中
Class tcls=self—>ISA(),获取当前类的元类,那么tcls就是当前类的元类
tcls=tcls—>getSuperclass(),获取元类的父类。
-isKindOfClass()方法中
[self class] == cls;当前类是否是元类
+isMemberOrClass()方法中
self->ISA() == cls,元类是否等于当前类
由此可知,对于NSObject和LGPerson来说元类不是当前类,因此re2和re3都返回0
但是有个问题,在isKindOfClass()两个方法中加断点,发现并没有走这两个函数
接下来打开汇编发现,并没找到isKindOfClass(),但是找到了objc_opt_isKindOfClass()方法
在源码中搜索objc_opt_isKindOfClass(),可以的到这个函数,打上断点,发现程序运行时都走这里的。
然而不同的是re1在这个for循环中走了两次,re3在这个循环中走了三次。结合图05的代码调试re1的过程可知,re1第一次走tcls只获取到地址,第二次才获取到NSObject。re3前两次也是只获取到地址,第三次才获取到NSObject。(只获取到地址,是因为找到了元类)
同理re5和re7在这个for循环中都只走了一次,是因为获取到当前类,tcls是有值的,所以直接跳出循环。所以re5和re7返回1。
re1和re3过程可以理解为:
对于NSObject来说,是NSObject—>NSObject根元类—>根元类父类,
NSObject根元类父类还是NSObject,因此re1返回1
对于LGPerson来说,是LGPerson—>LGPerson元类—>LGPerson根元类—>根元类父类,
LGPerson的根元类的父类是NSObject,因此re3返回0
-isMemberOrClass()方法中
- (BOOL)isMemberOfClass:(Class)cls { return [self class] == cls;}
re6和re8在代码运行过程中是走了这里,由此可知,对于NSObject和LGPerson来说对象指向的类是当前类,因此re6和re8都返回1
疑问:
在运行lgKindofDemo()之前,p走了三遍-isKindOfClass()方法,最终return no。
又定义了一个NSObject *n = [[NSObject alloc] init];,n是走了两遍-isKindOfClass()方法,最终return no
实例化之后,调用该对象为什么要走-isKindOfClass()这个方法,另外+isKindOfClass()方法在什么情况下使用