目录
- super关键字
----问题思考
----super
的结构
----objc_super
结构体
----class方法
的底层实现
----superclass方法
的底层实现- 总结
---- [super class] 总结
---- [super superclass] 总结- 补充
super关键字
-
问题思考
创建Person
类和其子类Student
。在Student
内部添加如下代码,观察两组打印结果:
NSLog(@"第一组----------");
NSLog(@"[self class] %@", [self class]);
NSLog(@"[self superclass] %@", [self superclass]);
NSLog(@"第二组----------");
NSLog(@"[super class] %@", [super class]);
NSLog(@"[super superclass] %@", [super superclass]);
打印结果:
第一组----------
[self class] Student
[self superclass] Person
第二组----------
[super class] Student
[super superclass] Person
如果super
代表的是父类,那么为什么self
和super
调用class
的结果相同?
-
super的结构
为Person
和Student
都添加run
方法。
在Student
执行run
方法时调用父类run
方法。
- (void)run {
[super run];
}
转成C++代码:
((void (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Student"))}, sel_registerName("run"));
整理一下:
struct objc_super sp = {
self,
[Person class],
};
objc_msgSendSuper(sp, @selector(run));
![](https://img.haomeiwen.com/i6545546/c95c0f96eb6d40dd.png)
可以看到使用super关键字调用方法时,底层使用的是objc_msgSendSuper
方法,且传入参数为objc_super
结构体和SEL
。
-
objc_super结构体
objc_super
的结构如下,包含消息接收者和消息接收者的父类两个成员:
struct __rw_objc_super {
struct objc_object *object; // 消息接收者
struct objc_object *superClass; // 消息接收者的父类,决定了方法从那个类开始查找。
};
通过 objc源码 message.h
中objc_msgSendSuper
方法注释可知,当调用方法时会先在superClass
中开始搜索方法实现。
-
class方法的底层实现
class
方法是在NSObject
内部实现的,源码:
- (Class)class {
return object_getClass(self);
}
返回消息接收者(对象)的具体类型
-
superclass方法的底层实现
superclass方法是在NSObject内部实现的,源码:
- (Class)superclass {
return class_getSuperclass(object_getClass(self));
}
返回消息接收者(对象)父类的class。
总结
![](https://img.haomeiwen.com/i6545546/d27f230a97efe41b.png)
super
调用方法,在底层实际上是通过objc_msgSendSuper
方法实现。- 传入的参数是一个
objc_super
结构体。objc_super
结构体的第一个参数是self,最终消息接收者
。- 先从传入的第二个参数是消息接收者的父类,所以
从该父类开始查找方法的实现
。
-
[super class] 总结
- 最终在
NSObject
中查到到方法class
,进行调用。返回消息接收者(对象)的具体类型。
所以打印[super class]
结果是Student
。
-
[super superclass] 总结
- 最终在
NSObject
中查到到方法superclass
,进行调用。返回消息接收者(对象)父类的class。
所以打印[super superclass]
结果是Person
。
补充
将super调用转成C++代码后,显示的底层实现是objc_msgSendSuper
方法,但真实的底层方法是objc_msgSendSuper2
。
可以通过汇编代码查看。
0x100003f2e <+46>: callq 0x100003f4c ; symbol stub for: objc_msgSendSuper2
callq _objc_msgSendSuper2
由此可见,
super
真实底层实现是_objc_msgSendSuper2
方法。
网友评论