super 学习笔记

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;
}

@end

int 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_Model
typedef struct objc_object Model;
typedef struct {} _objc_exc_Model;
#endif

struct Model_IMPL {
    struct NSObject_IMPL NSObject_IVARS;
};


/* @end */


// @implementation Model

static 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;
}

// @end

int 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 */
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值