• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

runtime - 面试题系列1 - Super

武飞扬头像
yokan_de_s
帮助1

1.Super

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

面试题是:上面这段代码,最终会输出什么

正常人应该会觉得[self class]肯定是输出student,[super class]肯定是Person,[self superclass]是Person,[super superclass]是NSObject

实际答案:Student,Student,Person,Person

原理:Super关键字到底做了什么,转c 就知道它底层干了啥

先cd到main.m的文件夹 xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m

输入这段,之后就转成了main.cpp

  1.  
    static instancetype _I_Student_init(Student * self, SEL _cmd) {
  2.  
    if (self = ((Student *(*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Student"))}, sel_registerName("init"))) {
  3.  
    NSLog((NSString *)&__NSConstantStringImpl__var_folders_td_r9wqf72n79db8c30dyg3pwsc0000gn_T_main_55b348_mi_0,((Class (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("class")));
  4.  
    NSLog((NSString *)&__NSConstantStringImpl__var_folders_td_r9wqf72n79db8c30dyg3pwsc0000gn_T_main_55b348_mi_1,((Class (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Student"))}, sel_registerName("class")));
  5.  
    NSLog((NSString *)&__NSConstantStringImpl__var_folders_td_r9wqf72n79db8c30dyg3pwsc0000gn_T_main_55b348_mi_2,((Class (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("superclass")));
  6.  
    NSLog((NSString *)&__NSConstantStringImpl__var_folders_td_r9wqf72n79db8c30dyg3pwsc0000gn_T_main_55b348_mi_3,((Class (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Student"))}, sel_registerName("superclass")));
  7.  
    }
  8.  
    return self;
  9.  
    }

代码很多,大部分都是内部操作,和一些转译操作什么的,核心的只有这一个函数,是初始化函数,把NSLog去掉,然后再简化一下

  1.  
    ((Class (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("class"));
  2.  
    ((Class (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Student"))}, sel_registerName("class")));
  3.  
    ((Class (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("superclass")));
  4.  
    ((Class (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Student"))};

然后可以看出superClass会调用SuperClass函数,而super关键字会调用 objc_msgSenderSuper这个函数,然后传入父类,问题就在于  superClass 和objc_msgSenderSuper做了些啥

  1.  
    /**
  2.  
    * Sends a message with a simple return value to the superclass of an instance of a class.
  3.  
    *
  4.  
    * @param super A pointer to an \c objc_super data structure. Pass values identifying the
  5.  
    * context the message was sent to, including the instance of the class that is to receive the
  6.  
    * message and the superclass at which to start searching for the method implementation.
  7.  
    * @param op A pointer of type SEL. Pass the selector of the method that will handle the message.
  8.  
    * @param ...
  9.  
    * A variable argument list containing the arguments to the method.
  10.  
    *
  11.  
    * @return The return value of the method identified by \e op.
  12.  
    *
  13.  
    * @see objc_msgSend
  14.  
    */
  15.  
    OBJC_EXPORT id _Nullable
  16.  
    objc_msgSendSuper(struct objc_super * _Nonnull super, SEL _Nonnull op, ...)
  17.  
    OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
  18.  
    #endif
学新通

这个函数目前我没看到开源代码,只找到了对应的解释,传入的是一个结构体,和一个函数,函数就是调用的那个比如[super class],那么这个函数就是class,根据调用不同这个函数也不同,然后是结构体

  1.  
    struct objc_super {
  2.  
    /// Specifies an instance of a class.
  3.  
    __unsafe_unretained _Nonnull id receiver;
  4.  
     
  5.  
    /// Specifies the particular superclass of the instance to message.
  6.  
    #if !defined(__cplusplus) && !__OBJC2__
  7.  
    /* For compatibility with old objc-runtime.h header */
  8.  
    __unsafe_unretained _Nonnull Class class;
  9.  
    #else
  10.  
    __unsafe_unretained _Nonnull Class super_class;
  11.  
    #endif
  12.  
    /* super_class is the first class to search */
  13.  
    };

这里就是结构体的定义,是一个接受者和一个接受者的父类,这个结构体就是,一个类和他的父类,这里的解释很清楚从父类搜索它的方法实现,本身调用者还是类本身,而返回值是返回的方法调用者,所以用了super 和不用super只是寻找这个方法的本身位置不一样,并不会影响返回值

************补充**************

上面superclass这个函数的源码,就是返回一个父类

  1.  
    - (Class)superclass {
  2.  
    return [self class]->superclass;
  3.  
    }

所以上述代码里面打印出父类的,只有调用了superclass函数的代码

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgabaje
系列文章
更多 icon
同类精品
更多 icon
继续加载