我們先創(chuàng)建兩個類Person和Student,Student繼承自Person類,接下來我們在Student打印如下代碼:
@implementation Student
- (void)run{
[super run];
NSLog(@"Student");
}
- (instancetype)init{
if (self = [super init]) {
NSLog(@"[self class] = %@",[self class]);//Student
NSLog(@"[self superclass] = %@",[self superclass]);//Person
NSLog(@"----------------------");
NSLog(@"[super class] = %@",[super class]);//Student
NSLog(@"[super superclass] = %@",[super superclass]);//Person
}
return self;
}
@end
發(fā)現(xiàn)super跟self好像效果都是一樣的。這是什么原因,那我們就需要去看看super方法的底層調(diào)用了。我們看下run方法底層是怎樣的?
- (void)run{
[super run];
NSLog(@"Student");
}
struct __rw_objc_super arg = {
(id)self,//消息接收者
(id)class_getSuperclass(objc_getClass("Student"))//消息接收者的父類
};
objc_msgSendSuper(arg,
@selector(run));
可以看到super是通過objc_msgSendSuper發(fā)送消息,其中arg中消息接收者還是self。傳進去的那個父類是表示直接從父類去查找方法,而不是跟往常一樣從當前對象查找。那么[super class]就是直接從父類Person去搜索,而class方法在NSObject里面,class的底層實現(xiàn)是這樣
- (Class)class{
return object_getClass(self);
}
class調(diào)用返回值取決于方法接收者self跟父類無關,所以打印的還是Student。
superClass的底層實現(xiàn)是這樣:
+ (id)superclass
{
return self->superclass;
}
- (id)superclass
{
return isa->superclass;
}
其實返回的就是消息接收者的父類
總結(jié):super的本質(zhì)是:(1)消息接收者還是當前對象,并不是父類。(2)super方法調(diào)用時是直接從父類去查找方法,而不是從當前對象開始查找
isMemberOfClass和isKindOfClass區(qū)別
- (BOOL)isMemberOfClass:(Class)cls {
return [self class] == cls;
}
- (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
if (tcls == cls) return YES;
}
return NO;
}
很明顯isMemberOfClass是判斷當前對象是否是這個類對象。
isKindOfClass稍微復雜一點,首先是拿當前對象的類對象去比較看是否相等,如果不相等就跟父類比,直到NSObject基類。