OC笔记 - super底层实现(objc4-723)


super底层实现

1 - 先看代码:有 Student和 Person两个类,继承关系如是 Student -> Person -> NSObject

// - Student.m

 1 #import "Student.h"
 2 
 3 @implementation Student
 4 
 5 - (instancetype)init{
 6     self = [super init];
 7     if (self) {
 8         
 9         NSLog(@"[self class] = %@",[self class]);
10         NSLog(@"[self superclass] = %@",[self superclass]);
11         NSLog(@"----------------------");
12         NSLog(@"[super class] = %@",[super class]);
13         NSLog(@"[super superclass] = %@",[super superclass]);
14     }
15     return self;
16 }
17 
18 @end

// - main.m

 1 #import 
 2 #import "Person.h"
 3 #import "Student.h"
 4 int main(int argc, const char * argv[]) {
 5     
 6     Person *p1 = [Person new];
 7     Student *stu1 = [Student new];
 8     
 9     return 0;
10     
11 }

预想的结果:[self class] = Student  [self superclass] = Person  [super Class] = Person  [super superclass] = NSObject

日志输出:self我们不难理解,但是 super和我们预想的不一样!

2 - 底层实现

① 为了了解 super实现原理,我们为 Person、Student新增一个 run方法

// - Person.h

#import 
@interface Person : NSObject

-(void)run;
@end

// - Person.m

#import "Person.h"
@implementation Person

-(void)run{
    
    NSLog(@"Person run.......");
}

@end

// - Student.h

#import "Person.h"
@interface Student : Person

-(void)run;

@end

// - Student.m

 1 #import "Student.h"
 2 @implementation Student
 3 
 4 - (instancetype)init{
 5     self = [super init];
 6     if (self) {
 7         
 8         NSLog(@"[self class] = %@",[self class]);
 9         NSLog(@"[self superclass] = %@",[self superclass]);
10         NSLog(@"----------------------");
11         NSLog(@"[super class] = %@",[super class]);
12         NSLog(@"[super superclass] = %@",[super superclass]);
13     }
14     return self;
15 }
16 
17 
18 -(void)run{
19     [super run];
20     NSLog(@"Student run.......");
21 }
22 
23 @end

② 接着把 Student.m编译成 C++代码,其中 run方法实现如下

static void _I_Student_run(Student * self, SEL _cmd) {
    ((void (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Student"))}, sel_registerName("run"));
    NSLog((NSString *)&__NSConstantStringImpl__var_folders_t5_d7bd_spn3hsfdqj994fdm9bh0000gn_T_Student_9b1e3e_mi_5);
}

我们把 C++代码精简成 OC风格

 1 static void _I_Student_run(Student * self, SEL _cmd) {
 2     
 3     // __rw_objc_super结构体
 4     objc_msgSendSuper((__rw_objc_super){
 5         (id)self,
 6         (id)class_getSuperclass(objc_getClass("Student"))
 7     },
 8                     
 9     sel_registerName("run"));// 同 @selector(run)
10 }

打开 runtime源码,打开 __rw_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 */
};

我们继续把 __rw_objc_super精简,有两个成员变量

struct objc_super {
    __unsafe_unretained _Nonnull id receiver;        // 消息接收者
    __unsafe_unretained _Nonnull Class super_class;  // 父类

};

那么回过头来看我们 run方法的实现,其实就是这样子

static void _I_Student_run(Student * self, SEL _cmd) {
    
    // 传入了一个 __rw_objc_super结构体
    objc_msgSendSuper((__rw_objc_super){
        
        self,// Student
        class_getSuperclass(objc_getClass("Student")) //  [Person class]
    },
                
    // 调用 @selector(run)
    sel_registerName("run"));
}

我们看一下 objc_msgSendSuper的参数说明,就知道了 Student中的 run方法中的 [super run]调用的方法是从父类 Person中的 run方法开始调用,但是!它的消息接收者传进的仍然是 self = Student

也就是说我们刚开是的代码其实是这样

 1 - (instancetype)init{
 2     self = [super init];
 3     if (self) {
 4         
 5         NSLog(@"[self class] = %@",[self class]);           // Student
 6         NSLog(@"[self superclass] = %@",[self superclass]); // Person
 7         NSLog(@"----------------------");
 8         
 9 
10         NSLog(@"[super class] = %@",[super class]);// Student
11         // 这里的 super是从父类 Person开始调用 class
12         // 我们知道 class是 NSObect中的方法,它会一级级地向上查找直至找到 NSObect的 class方法并调用
13         // 而 class的实现是 -(Class)class{ return object_getClass(self);}
14         // 就是说 [super class] 传入的消息接收者是 Student从未改变
15         // 所以输出的是 Student
16         
17     
18         NSLog(@"[super superclass] = %@",[super superclass]);// Person
19         // superclass 获取的是 Person类对象
20         // -(Class)superClass{ return object_getSuperClass(object_getClass(self));}
21         // super传入的消息接收者依旧是 self = Student,但是最后返回的是 Person
22     }
23     return self;
24 }

结语

1 - [super message]底层实现

① 消息接收者仍然是子类对象

② 调用方法是从父类中开始查询