一、创建类
- Person 类:继承至 NSObject 类
- SubPerson 类:继承至 Person 类
- Person 类中有一个对象方法 test
- SubPerson类中实现此方法,并在此方法中写
- [self class]
- [self superclass]
- [super class]
- [super superclass]
- 外界调用 subPerson 的 test 方法。
代码如下:
Person.h
@interface Person : NSObject
- (void)test;
@end
SubPerson.m
#import "SubPerson.h"
@implementation SubPerson
- (void)test {
NSLog(@"SubPerson - test");
// 打印结果:SubPerson - Person - SubPerson - Person
NSLog(@"%@ - %@ - %@ - %@", [self class], [self superclass], [super class], [super superclass]);
}
@end
二、解释 SubPerson 类中的self、super 、 class、superclass
-
class
: 获取当前方法调用者的类 -
superclass
: 获取当前方法调用者的父类 -
self
: 当前类,是一个指针 -
super
: 仅仅是一个编译指示器,只是给编译器看的,不是一个指针 -
super
的本质:当编译器看到super
这个标志,就会让当前对象去调用父类的方法,本质还是当前对象在调用。 -
如何判断
super
不是一个指针? 打印一下就知道了。指针是可以打印的。
// 不报错
NSLog(@"%@",self);
// 报错:Use of undeclared identifier 'super' - 没有定义 super
NSLog(@"%@",super);
三、在subPerson 类的test方法调用 [super test];
- 在
subPerson
类的test
方法调用[super test]
; - 在
Person
类的test
方法中写入代码NSLog(@"%@ - %@ - %@ - %@", [self class], [self superclass], [super class], [super superclass]);
- 打印结果为:
SubPerson - Person - SubPerson - Person
这是因为:
subPerson
类中的[super test]
的super
相当于self
。(如不记得,请看二中的super
定义)。- 所以
person
类 中打印的相当于subperson
类的打印。
四、super 的底层实现
-
创建命令行项目
macOS -> Application -> Command Line Tool -> Clang
-
在 main.m 中写一个类,如下方代码:
-
我们要看的是
[super description]
中的super
-
打开
main.m
所在的位置 -
在终端输入
cd main.m
所在的位置 -
$ clang -rewrite-objc main.m
-
如果出现下方图片中的错误
-
修改错误:
偏好设置 -> locations -> Command Line Tools -> Xcode 8 -> 再次运行终端命令 -> 成功
-
这时候,项目的文件夹中会有一个
main.cpp
文件. -
打开 -> command + F 查找 -> @autoreleasepool
-> 在这个属性的上面就是 我们自定义的person
类 .
-
从上面的代码可以看到,最终 自定义的类会变成结构体
-
把方法转换成函数
static NSString * _I_Person_description 函数
-
把函数中的强转类型去掉
// 原函数
((NSString *(*)(__rw_objc_super *, SEL))(void *) objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Person"))},sel_registerName("description"));
// 1. 第一次删除 (NSString *(*)(__rw_objc_super *, SEL))
objc_msgSendSuper((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Person"))},sel_registerName("description"));
// 2. 第二次删除 (__rw_objc_super)
objc_msgSendSuper({(id)self, (id)class_getSuperclass(objc_getClass("Person"))},sel_registerName("description"));
// 3. 第三次删除 删除 (id )
objc_msgSendSuper({self, class_getSuperclass(objc_getClass("Person"))},sel_registerName("description"));
objc_msgSendSuper
函数的形参是什么?struct objc_super *super
,SEL op
, …- 第一个参数传的是结构体,一个
objc_super
的结构体
objc_super
的代码
- receiver : 消息发送者
# if !defined(__cplusplus) && !__OBJC2__
- 如果不是
c++
并且 不是OC
代码的话,走Class class
- 如果是,走
Class super_class
- 如果不是
- 第一个形参是
消息发送者
,第二个形参是sel_registerName("description")
- 对应 ->
{self, class_getSuperclass(objc_getClass("Person"))},sel_registerName("description")
消息发送者, Class super_class
self = 消息发送者
class_getSuperclass(objc_getClass("Person")) = Class super_class
调用的方法 = sel_registerName("description")