下面会打印什么?
- (id)init {
self = [super init];
if (self)
{
NSLog(@"%@", NSStringFromClass([self class]));
NSLog(@"%@", NSStringFromClass([super class]));
}
return self;
}
@end
self:当前这个对象
super:编译器标示符,给编译器看的,底层用另外一个方法发消息
super就是self,去调用父类方法
让当前对象调用父类方法,本质上还是self在调用
- 无论是
[self class]
还是[super class]
,接受消息者都是Son对象- super与self不同的是,self调用是在子类Son中找class方法
- super调用是在父类Father中找class方法
- 编译后,调用super标识符修饰的方法,会用
objc_msgSendSuper
函数进行消息的发送,而不是objc_msgSend
深度解析
调用[self class]方法时
- 转化为objc_msgSend函数
- 先在 Son 这个类里面去找
- (Class)class
方法,没有就去父类 Father里找,也没有,最后在 NSObject类中发现这个方法
NSObject类中- (Class)class
的实现如下:
- (Class)class {
// 返回实例的isa指针指向的类
return object_getClass(self);
}
[self class] == objc_msgSend(self, "class");
打印:Son
调用[super class]方法时
- super为编译器标示符
- 向super发送的消息被编译成objc_msgSendSuper
- 不管是self、还是super指向消息接受者是一样的
转化为objc_msgSendSuper,函数定义如下:
id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
// objc_super的结构体
struct objc_super {
id receiver;
Class super_class; // 记录当前父类
};
-
receiver
,类的实例objc_super->receiver=self
- 消息的接受者还是
self
-
super_class
,记录当前类的父类-
(id)class_getSuperclass(objc_getClass(“Son”))
- 该函数输出结果为 Father
- 去 Father这个类里去找
- (Class)class
,没有,然后去NSObject类去找
-
- super只是告诉编译器,去查找父类中的class方法
- 当找到之后,使用objc_super->receiver即self进行调用
[super class]转换流程
[super class] → objc_msgSendSuper(objc_super{self, superclass}, sel_registerName("class")) → objc_msgSend(objc_super->self, sel_registerName("class")) === [self class]
打印:Son
demo2:理解super
@implementation Father
- (void)test
{
NSLog(@"%@, %@, %@", [self class], [self superclass], [super class]);
}
@end
--------------------------------
@implementation Son
/**
class:获取方法调用者类名
superclass:获取方法调用者的父类类名
super:指向父类的标识,编译器修饰符,不是指针
*/
- (void)test
{
// 谁调用这个方法,self就是谁!
NSLog(@"%@", self);
// NSLog(@"%@", super);
// 函数里也没有定义super
// self是隐藏参数,super就是个标识符,和const差不多!
// NSLog(@"%@, %@, %@", [self class], [self superclass], [super class]);
// Son, Father, Son
[super test];
// Son, Father, Son
}
@end
super不是父类对象!!
- 和const差不多
- self是对象、是指针可以打印,super不是指针,不能打印
- 本质还是拿到当前对象去调用父类方法
- super就是self去调用父类方法
- 只是去父类方法里找,而不是找自己的
网友评论