为了方便讲解,以下列出isMemberOfClass和isKindOfClass的实例方法和类方法底层实现
由上图可知:
isMemberOfClass:
此处YYPerson继承至NSObject
分析:
实例方法:因为只是简单的判断方法调用者的类对象是否等于传入的cls,所以[p1 isMemberOfClass:[NSObject class]] 为0,[p1 isMemberOfClass:[YYPerson class]]为1
类方法:是通过判断object_getClass((id) self ) == cls,我们可知类方法中的self是类对象,所以是判断元对象是否等于cls,很显然YYPerson元对象不是NSObject类对象,也不等于YYPerson类对象,所以[YYPerson isMemberOfClass:[NSObject class]]为0,[YYPerson isMemberOfClass:[YYPerson class]]为0。
补充:
object_getClass(id obj):此方法如果传入的是instance对象,返回class对象。如果是class对象,返回mate-class对象。如果是meta-class对象,返回NSObject的meta-class对象
objc_getClass(const char *) :传入字符串类名,返回对应类对象
-(Class)class; + (Class) class; : 返回的是类对象
isKindOfClass:
分析:
实例方法:实例方法中[self class],返回类对象,即tcls为类对象,首先会判断tcls是否等于cls,如果不等于将继续遍历,tcls supperClass指针继续往上查找。
[p1 isKindOfClass:[NSObject class]]:
因为tcls 为p1类对象,因为不等于[NSObject class],所以继续遍历(supperClass指针指向可以查看OC对象内存布局这一节),找到[NSObject class],此时相等所以打印1;
[p1 isKindOfClass:[YYPerson class]]:
因为tcls 为p1类对象,等于[YYPerson class]所以打印1;
类方法:类方法中object_getClass((id) self ),返回meta对象,即tcls为meta对象,首先会判断tcls是否等于cls,如果不等于将继续遍历,tcls supperClass指针继续往上查找。
[YYPerson isKindOfClass:[NSObject class]]:
因为tcls 为p1元对象,因为不等于[NSObject class],所以继续遍历(supperClass指针指向可以查看OC对象内存布局这一节),找到NSObject 元对象,此时仍然不相等,所以继续遍历,由于Root Class(meta)的supperClass指针指向,Root Class(class),(可查看OC对象内存布局指针指向图,或者注意点说明) 所以NSObject 元对象的supperClass 最终指向NSObject类对象,所以相等,打印1
[YYPerson isKindOfClass:[YYPerson class]]:
因为tcls 为p1元对象,因为不等于YYPerson 类对象,所以继续遍历找到NSObject 元对象,此时仍然不相等,所以继续遍历,找到NSObject类对象仍然不相等,继续遍历,因为NSObject的类对象supperClass指针为nil,所以不相等,打印0;
总结:
isKindOfClass和isMemberOfClass:
两者都能检测一个对象是否是某个类的成员, 两者之间的区别是:isKindOfClass不但可以用来确定一个对象是否是一个类的成员,也可以用来确定一个对象是否是派生自该类的类的成员 ,而isMemberOfClass做不到后一点。
实例方法都是判断对象的类对象是否==传入参数,类方式都是判断元对象是否== 传入参数。
但是isKindOfClass当判断不等于时,还会去查找superClass指针指向的对象是否等于传入参数。而isMemberOfClass不会。因此isKindOfClass可以确定一个对象是否是一个类的成员,也可以用来确定一个对象是否是派生自该类的类的成员。