super 学习笔记

来源:互联网 发布:阿里云服务器1核2g 编辑:程序博客网 时间:2024/05/15 23:52

super是一个编译指示器,仅仅是给编译器看的,不是一个指针。只要编译器看到super这个标志,就会让当前对象调用父类的方法,但是方法的调用者还是当前对象本身。

// ----- Model.h -----#import <Foundation/Foundation.h>@interface Model : NSObject//仅仅开放一个方法,不实现- (void)test;@end// ----- Model.m -----#import "Model.h"@implementation Model@end// ----- SubModel.h -----#import "Model.h"// 继承自Model@interface SubModel : Model  @end// ----- SubModel.m -----#import "SubModel.h"@implementation SubModel// SubModel继承自Model,调用父类定义的方法test- (void)test{    // class: 获取class方法调用者的类    // superclass: 获取superclass方法调用者的父类    // super: 仅仅是一个编译指示器,就是给编译器看的,不是一个指针    // 本质:只要编译器看到super这个标志,就会让当前对象去调用父类方法,本质还是当前对象在调用    NSLog(@"self class:%@",[self class]);    NSLog(@"self superclass:%@",[self superclass]);    NSLog(@"super class:%@",[super class]);    NSLog(@"super superclass:%@",[super superclass]);}@end
// ------ ViewController.m ------- (void)viewDidLoad {    [super viewDidLoad];    SubModel *subModel = [[SubModel alloc] init];    [subModel test];}

调用结果

调用结果

假如在SubModel中调用父类的test方法,将4个Log放入父类的test方法中,输出结果还是和上例一样。因为self还是SubModel对象,它仅仅只是调用了父类的方法。

// ------ SubModel.m ------// SubModel继承自Model,调用父类定义的方法test- (void)test{    // class: 获取class方法调用者的类    // superclass: 获取superclass方法调用者的父类    // super: 仅仅是一个编译指示器,就是给编译器看的,不是一个指针    // 本质:只要编译器看到super这个标志,就会让当前对象去调用父类方法,本质还是当前对象在调用//    NSLog(@"self class:%@",[self class]);//    NSLog(@"self superclass:%@",[self superclass]);//    NSLog(@"super class:%@",[super class]);//    NSLog(@"super superclass:%@",[super superclass]);    //调用父类的test方法    [super test];}
// ------ Model.m ------- (void)test{    //结果还是 SubModel Model SubModel Model, 虽然调用的是父类Model的test方法,self还是SubModel对象。    NSLog(@"self class:%@",[self class]);    NSLog(@"self superclass:%@",[self superclass]);    NSLog(@"super class:%@",[super class]);    NSLog(@"super superclass:%@",[super superclass]);}

调用结果

调用结果

super底层代码

  • 新建一个命令行项目(Command Line Tool)
//main.m#import <Foundation/Foundation.h>@interface Model : NSObject@end@implementation Model- (instancetype)init{    self = [super init];    return self;}@endint main(int argc, const char * argv[]) {    @autoreleasepool {        // insert code here...        NSLog(@"Hello, World!");    }    return 0;}
  • 打开终端,cd进包含main.m文件的文件夹(注意,这里是文件夹!!!),执行命令 clang -rewrite-objc main.m,在该文件夹下会多出一个.cpp后缀的文件,打开该文件,cmd+F,搜索@autoreleasepool,找到底层实现代码
// main.cpp#ifndef _REWRITER_typedef_Model#define _REWRITER_typedef_Modeltypedef struct objc_object Model;typedef struct {} _objc_exc_Model;#endifstruct Model_IMPL {    struct NSObject_IMPL NSObject_IVARS;};/* @end */// @implementation Modelstatic instancetype _I_Model_init(Model * self, SEL _cmd) {    // 这里就是我们要找的底层代码     self = ((Model *(*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Model"))}, sel_registerName("init"));    return self;}// @endint main(int argc, const char * argv[]) {    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;         NSLog((NSString *)&__NSConstantStringImpl__var_folders_y5_y2q0fd790k900f9k1lxkz7ww0000gn_T_main_0aa3fc_mi_0);    }    return 0;}
  • super的底层实现代码
((Model *(*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Model"))}, sel_registerName("init"))// 将强制类型转换全部删除掉objc_msgSendSuper({self,class_getSuperclass(objc_getClass("Model"))},sel_registerName("init"))

objc_msgSendSuper(<#struct objc_super *super#>, <#SEL op, …#>) 第一个参数是个objc_super结构体,第二个参数是SEL

// receiver是指类的实例,super_class则是指该实例的父类struct objc_super {    /// Specifies an instance of a class.    __unsafe_unretained 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 Class class;#else    __unsafe_unretained Class super_class;#endif    /* super_class is the first class to search */};
0 0
原创粉丝点击