isKindOfClass和isMemberOfClass解析
先出一道题(其中Person类继承NSObject类)
BOOL rs1 = [[NSObject class] isKindOfClass:[NSObject class]];
BOOL rs2 = [[NSObject class] isMemberOfClass:[NSObject class]];
BOOL rs3 = [[Person class] isKindOfClass:[Person class]];
BOOL rs4 = [[Person class] isMemberOfClass:[Person class]];
NSLog(@"rs1 = %d,rs2 = %d,rs3 = %d,rs4 = %d",rs1,rs2,rs3,rs4);
有没有哪位同学的答案是
1,1,1,0 //嘻嘻,我一开始也是这样觉得的。
可惜了,不是哦,结果是:
1,0,0,0
为啥子嘞!!!!!!!
文档描述为:
isKindOfClass:
returns a Boolean value that indicates whether the receiver is an instance of given class or an instance of any class that inherits from that class.(确定一个对象是否是一个类的成员,或者是派生自该类的成员.)
isMemberOfClass:
Returns a Boolean value that indicates whether the receiver is an instance of a given class.(确定一个对象是否是当前类的成员.)
另外通过阅读Runtime的源码,看到了isKindOfClass和isMemberOfClass的源码实现:
+ (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->superclass) {
if (tcls == cls) return YES;
}
return NO;
}
- (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
if (tcls == cls) return YES;
}
return NO;
}
包括类方法和实例方法,平常我们接触多的是实例方法。
Person *p = [[Person alloc] init];
[p isKindOfClass:[Person class]];
[p isMemberOfClass:[Person class]];
不过在上面的题目中,涉及到了类方法。关于对象,类,元类(MetaClass)之间的关系,我直接贴上经典图,这个大家请另外搜索相关内容。
我们一句一句来分析
先提取一下公共调用的方法(函数)
//下面代码涉及到的方法与函数
//类对象返回自身
+ (Class)class {
return self;
}
//如果obj不是nil,就返回对象isa指针指向的对象
Class object_getClass(id obj)
{
if (obj) return obj->getIsa();
else return Nil;
}
1. [[NSObject class] isKindOfClass:[NSObject class]];
[[NSObject class] isKindOfClass:[NSObject class]];
+ (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = object_getClass((id)self); tcls; tcls = tcls->superclass) {
if (tcls == cls) return YES;
}
return NO;
}
其中,类对象发送class消息的时候,返回的是自身,也就是类对象本身。所以 执行 的是
+ (BOOL)isKindOfClass:(Class)cls;
因为NSObject是根类,所以它的isa指针指向的是NSObject的元类,另外NSObject元类的superclass是NSObject本身。
所以isKindOfClass:这个类方法中的循环会返回YES。
这里我简单写一下循环的每一步:
+ (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = object_getClass((id)self); tcls; tcls = tcls->superclass) {
if (tcls == cls) return YES;
}
return NO;
}
//以下是执行的步骤
1.Class tcls = object_getClass((id)self) 执行后,tcls是NSObject元类,所以返回NO;
2.tcls目前是NSObject元类,tcls不是nil所以循环会继续执行,
tcls = tcls->superclass,
上面说了NSObject元类的父类是NSObject本身;所以tcls目前是NSObject本身;
3.继续执行语句,发现tcls == cls,所以返回YES。循环结束。
所以值为 YES。
2. [[NSObject class] isMemberOfClass:[NSObject class]];
[[NSObject class] isMemberOfClass:[NSObject class]];
+ (BOOL)isMemberOfClass:(Class)cls {
return object_getClass((id)self) == cls;
}
我们直接分析类方法isMemberOfClass:,其中object_getClass((id)self)返回的是NSObject元类,但是cls是NSObject本身,所以不相等。
所以值为 NO。
3. [[Person class] isKindOfClass:[Person class]];
这边直接分析:
- [Person class]的值为Person类本身;
2.调用isKindOfClass:类方法,执行循环的步骤:
+ (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = object_getClass((id)self); tcls; tcls = tcls->superclass) {
if (tcls == cls) return YES;
}
return NO;
}
执行步骤:
1. Class tcls = object_getClass((id)self) tcls是Person元类;
2. 执行循环语句,不过,tcls != cls,因为tcls 是Person元类, cls是Person类;
3. tcls = tcls->superclass,tcls为 NSObject元类;
4. 再次执行循环语句,不过,tcls != cls,因为tcls是NSObject元类,cls是Person类;
5. tcls = tcls->superclass,tcls为NSObject类;
6. 再次执行循环语句,不过,tcls != cls,因为tcls是NSObject类,cls是Person类;
7. tcls = tcls->superclass,tcls为nil,因为NSObject类的父类是nil;
8. 再次执行循环语句,return NO;结束循环
所以值为 NO。
4. [[Person class] isMemberOfClass:[Person class]];
[[Person class] isMemberOfClass:[Person class]];
+ (BOOL)isMemberOfClass:(Class)cls {
return object_getClass((id)self) == cls;
}
直接分析,因为object_getClass((id)self) 获取到的是 Person元类,而cls是Person类。
所以值为 NO。
分析完毕,至于isKindOfClass和isMemberOfClass的实例方法较为简单,大家可自行尝试!
over!