前言:先来张熟悉又陌生的图:
【面试题一】
iskindOfClass
& isMemberOfClass
的理解下面代码,怎么打印,并分析原因
int main(int argc, const char * argv[]) {
@autoreleasepool {
//-----使用 iskindOfClass & isMemberOfClass 类方法
BOOL re1 = [(id)[NSObject class] isKindOfClass:[NSObject class]]; //
BOOL re2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]]; //
BOOL re3 = [(id)[LGPerson class] isKindOfClass:[LGPerson class]]; //
BOOL re4 = [(id)[LGPerson class] isMemberOfClass:[LGPerson class]]; //
NSLog(@" re1 :%hhd\n re2 :%hhd\n re3 :%hhd\n re4 :%hhd\n",re1,re2,re3,re4);
//------iskindOfClass & isMemberOfClass 实例方法
BOOL re5 = [(id)[NSObject alloc] isKindOfClass:[NSObject class]]; //
BOOL re6 = [(id)[NSObject alloc] isMemberOfClass:[NSObject class]]; //
BOOL re7 = [(id)[LGPerson alloc] isKindOfClass:[LGPerson class]]; //
BOOL re8 = [(id)[LGPerson alloc] isMemberOfClass:[LGPerson class]]; //
NSLog(@" re5 :%hhd\n re6 :%hhd\n re7 :%hhd\n re8 :%hhd\n",re5,re6,re7,re8);
}
return 0;
}
打印如下:
re1 :1
re2 :0
re3 :0
re4 :0
re5:1
re6:1
re7:1
re8:1
结果已给,你细品,你细细的品;接下来,解释一波,有错,请留言,不要发红包。
源码分析一波
-isKindOfClass
源码解析(实例方法 & 类方法)
//--isKindOfClass---类方法、对象方法
//+ isKindOfClass:第一次比较是 获取类的元类 与 传入类对比,再次之后的对比是获取上次结果的父类 与 传入 类进行对比
+ (BOOL)isKindOfClass:(Class)cls {
// 获取类的元类 vs 传入类
// 根元类 vs 传入类
// 根类 vs 传入类
// 举例:LGPerson vs 元类 (根元类) (NSObject)
for (Class tcls = self->ISA(); tcls; tcls = tcls->superclass) {
if (tcls == cls) return YES;
}
return NO;
}
//- `isKindOfClass`:第一次是获取对象类 与 传入类对比,如果不相等,后续对比是继续获取上次 类的父类 与传入类进行对比
- (BOOL)isKindOfClass:(Class)cls {
/*
获取对象的类 vs 传入的类
父类 vs 传入的类
根类 vs 传入的类
nil vs 传入的类
*/
for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
if (tcls == cls) return YES;
}
return NO;
}
-
isMemberOfClass
源码解析(实例方法 & 类方法)
//-----类方法
//+ isMemberOfClass : 获取类的元类,与 传入类对比
+ (BOOL)isMemberOfClass:(Class)cls {
return self->ISA() == cls;
}
//-----实例方法
//- isMemberOfClass : 获取对象的类,与 传入类对比
- (BOOL)isMemberOfClass:(Class)cls {
return [self class] == cls;
}
"强行解释一波"是有依据的,总结如下:
<article class="_2rhmJa">
-
isKindOfClass
- 类方法:
元类 --> 根元类 --> 根类 --> nil
与传入类
的对比 - 实例方法:
对象的类 --> 父类 --> 根类 --> nil
与传入类
的对比
- 类方法:
-
isMemberOfClass
- 类方法:
类的元类
与传入类
对比 - 实例方法:
对象的父类
与传入类
对比
- 类方法:
案例代码执行结果分析
根据源码的分析,来分析代码执行的结果为什么是0
或者1
使用类方法结果解析
-
re1 :1 ,是
NSObject
与NSObject
的对比,使用+isKindOfClass
- NSObject(传入类,即
根类
) vs NSObject的元类即根元类
-- 不相等 - NSObject(传入类,即
根类
) vs 根元类的父类即根类
-- 相等,返回1
- NSObject(传入类,即
-
re2 :0 ,是
NSObject
与NSObject
的对比,使用+isMemberOfClass
- NSObject
根类
(传入类) vs NSObject的元类即根元类
-- 不相等
- NSObject
-
re3 :0 ,是
LGPerson
与LGPerson
的对比,使用+isisKindOfClass
- LGPerson(传入
类
) vs LGPerson的元类即元类
LGPerson -- 不相等 - LGPerson(传入
类
) vs 元类LGPerson的父类即根元类
-- 不相等 - LGPerson(传入
类
) vs 根元类的父类即根类
-- 不相等 - LGPerson(传入
类
) vs 根类的父类即nil
-- 不相等
- LGPerson(传入
-
re4 :0 ,是
LGPerson
与LGPerson
的对比,使用+isMemberOfClass
- LGPerson(传入
类
) vs元类
-- 不相等
- LGPerson(传入
使用实例方法结果解析
-
re5 :1 ,是
NSObject对象
与NSObject
的对比,使用-isKindOfClass
- NSObject(传入类,即根类) vs 对象的类即NSObject根类 -- 相等
-
re6 :1 ,是
NSObject对象
与NSObject
的对比,使用-isMemberOfClass
- NSObject(传入类,即根类) vs 对象的类即NSObject根类 -- 相等
-
re7 :1 ,是
LGPerson对象
与LGPerson
的对比,使用-isKindOfClass
- LGPerson(传入类) vs 对象的类即LGPerson -- 相等
-
re8 :1 ,是
LGPerson对象
与LGPerson
的对比,使用-isMemberOfClass
- NSObject(传入类) vs 对象的类即LGPerson -- 相等