我们都知道self是指向当前调用者的指针,那么super呢?
有的同学会说平时用super调用父类的方法,会说这是指向父类的指针,其实不是的,super仅仅是一个编译器的指示器,就是给编译器看的,不是一个指针;本质还是当前对象的调用者(self),只要编译器看到super这个标志就会让当前对象去调用父类方法。接下来使用几个示例class、superClass和使用clang编译指令来查看编译或代码示例来证明:
先定义两个类Persion,SubPersion,其中SubPersion继承Persion。现在SubPersion中定义并实现test方法。如下示例
#import "SubPersion.h"
@implementation SubPersion
-(void)test{
NSLog(@"%@ %@ %@ %@",[self class],[self superclass],[super class],[super superclass]);
}
@end
打印的日志如下。
解下来在父类中实现test,再子类调用test
#import "Persion.h"
@implementation Persion
-(void)test{
NSLog(@"%@ %@ %@ %@",[self class],[self superclass],[super class],[super superclass]);
}
@end
#import "SubPersion.h"
@implementation SubPersion
-(void)test{
[super test];
}
@end
通过两个例子的日志打印,可看出,super不是指向父类的指针,只是一个编译器指示器,实现还是当前调用者self
下面通过将下列代码使用clang -rewrite-objc
命令编译,看编译后的的代码
#import <Foundation/Foundation.h>
@interface Persion : NSObject
@end
@implementation Persion
- (NSString *)description
{
return [super description];
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
}
return 0;
}
转换后我们看这段代码如下。
static NSString * _I_Persion_description(Persion * self, SEL _cmd) {
return ((NSString *(*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Persion"))}, sel_registerName("description"));
}
// @end
int main(int argc, const char * argv[]) {
/* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
}
return 0;
}
将强制转换去出后代码如下
static NSString * _I_Persion_description(Persion * self, SEL _cmd) {
return objc_msgSendSuper({(self, class_getSuperclass(objc_getClass("Persion"))}, sel_registerName("description"));
}```
通过查看objc_msgSendSuper方法的源码可看出第一个参数是结构图objc_super,而结构体定义如下
struct objc_super {
/// Specifies an instance of a class.
__unsafe_unretained _Nonnull id receiver;
/// Specifies the particular superclass of the instance to message.
#if !defined(__cplusplus) && !OBJC2
/* For compatibility with old objc-runtime.h header /
__unsafe_unretained _Nonnull Class class;
#else
__unsafe_unretained _Nonnull Class super_class;
#endif
/ super_class is the first class to search */
};
结构体的第一个参数为消息发送者,而第二个参数表明为父类,通过编译后看出,发送消息是self。