isKindOf vs isMemberOf
2020-01-03 本文已影响0人
xxxxxxxx_123
首先我们来看看isKindOf、isMemberOf作为实例方法和类方法实现的源码:
+ (Class)class {
return self;
}
- (Class)class {
return object_getClass(self);
}
+ (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;
}
分析:
- +isKindOfClass作为类方法调用的时候,object_getClass传入的参数是类,返回的是元类,多层级遍历之后根元类的父类就是根类,所以isKindOfClass我们只需要判断当前调用的元类、父类和比较类是否相同即可。
- -isKindOfClass作为实例方法调用的时候,由于此时self是一个实例对象,[self class],则返回的是当前实例对象的类,所以isKindOfClass需要判断当前调用的类、其父类和比较类是否相同即可。
+ (BOOL)isMemberOfClass:(Class)cls {
return object_getClass((id)self) == cls;
}
- (BOOL)isMemberOfClass:(Class)cls {
return [self class] == cls;
}
分析:
- +isMemberOfClass作为类方法调用的时候,object_getClass返回的是调用者的元类,所以只需要判断调用者的元类和比较类是否相等即可。
- -isMemberOfClass作为实例方法调用的时候,就是比较调用实例的类是否和比较类相同。
eg:
BOOL re1 = [(id)[NSObject class] isKindOfClass:[NSObject class]]; // 1
BOOL re2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]]; // 0
BOOL re3 = [(id)[TPerson class] isKindOfClass:[TPerson class]]; // 0
BOOL re4 = [(id)[TPerson class] isMemberOfClass:[TPerson class]]; // 0
NSLog(@" re1 :%hhd\n re2 :%hhd\n re3 :%hhd\n re4 :%hhd\n",re1,re2,re3,re4);
BOOL re5 = [(id)[NSObject alloc] isKindOfClass:[NSObject class]]; // 1
BOOL re6 = [(id)[NSObject alloc] isMemberOfClass:[NSObject class]]; // 1
BOOL re7 = [(id)[TPerson alloc] isKindOfClass:[TPerson class]]; // 1
BOOL re8 = [(id)[TPerson alloc] isMemberOfClass:[TPerson class]]; // 1
NSLog(@" re5 :%hhd\n re6 :%hhd\n re7 :%hhd\n re8 :%hhd\n",re5,re6,re7,re8);
我们分析一下:
[(id)[NSObject class] isKindOfClass:[NSObject class]]
[NSObject class]返回的是NSObject类,所以我们调用的是+isKindOfClass,比较的也是[NSObject class]NSObject类,+isKindOfClass比较的是NSObject类的元类及其元类的父类是否等于NSObject类,根据isa和superClass关系图可以知道,NSObject类的元类的父类就是NSObject,和比较对象NSObject相等,所以re1 = 1。
同理,可以得出其他的结果。
最后附图一张:
image