美文网首页
从源码理解runtime之super、superclass知识点

从源码理解runtime之super、superclass知识点

作者: GDCoder | 来源:发表于2021-04-01 12:57 被阅读0次

    跟大家分享一道关于super和superclass的面试题,也是比较常见的面试题,请看下面的代码:

    请问当前的4个结果输出是多少?我们平时写代码估计也不会这么写,面试官问你这些问题,主要是看你对super和superclass是否理解透彻,接下来我们就去分析一下.

    首先我们肯定是知道[self class]这个肯定就是当前类,也就是GDStudent;而[self superclass]肯定是它的父类GDPerson

    这两个应该是毫无疑问,我们看一下是不是这样,请看下图代码:

    这两个是非常明显的答案,我们就来看一下super是怎么回事,这样,我们先来随便在GDStudent写一个方法比如 -(void)test;

    .m文件加上实现 如下图:

    是不是我们只要搞清楚test里面是怎么调用的,我们就知道super到底做了什么事!所以老样子,我们把GDStudent.m转成底层的c++文件看一下具体的实现是什么样的.只要搞清楚了[super test]做了什么事,其他的问题就迎刃而解了(转成c++的代码我前面说了很多次: xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc GDStudent.m -o GDStudent.m-arm64.cpp)

    所以我们只要关注绿色框框的代码就行了,我们把上面的代码简化一下,这样看得更清楚.

    上面的就是源码的简化版本,是一摸一样的效果,这里的[super test]就是arg给@selector(test)发一个class_getSuperclass消息,接下来,我们就看一下这个_objc_super的源码里面是怎么实现的(注意这里是去找objc的苹果开源源码,不是刚刚转换的c++的源码,下载地址之前分享了好多次,我现在下载的是787版本),看看结构体里面到底做了什么事!如下图

    __rw_objc_super源码实现

    __rw_objc_super我们再可以简化一下我们离答案越来越近了,请看简化后的如下图:

    这里应该也是非常的清晰吧 self:就是上面的receiver;class_getSuperclass(objc_getClass("GDStudent") :就是上面的 super_class.

    接下来我们看最后一个objc_msgSendSuper这个的源码实现,就能解决这个问题了,请看下面的源码:

    这里面解释的非常清楚:2个参数,第一个参数就是消息接收者,receiver也就是self,前面的结构体定义很清楚知道;第二个就是用来开始查找方法开始地方.

    说白了,调用方法[super run]在开始找run方法的时候,首先是从父类的类对象(GDPerson)开始找!消息接收者还是self(GDStudent)这个结论应该很清楚吧;

    结论

    调用super方法的时候,是首先从父类的类对象开始查找方法,消息接收者还是当前类.

    好了,知道这个结果,我们继续去看面试题,大家猜一下这两个结果是啥?

    //        NSLog(@"%@",[super class]);

    //        NSLog(@"%@",[super superclass]);

    我们先来看一下结果:

    结果运行

    是不是有很诧异的同学.首先class方法在哪?对于一个oc对象,都有class方法这个是吧,所以class方法在NSObject里面,这里应该是没有什么问题.

    现在我们去objc源码再去看一下class和superclass的底层实现,请看下图:

    所以到这里我们很清楚,为什么会出现上面的结果:

            NSLog(@"%@",[self class]);

            NSLog(@"%@",[self superclass]);

            NSLog(@"%@",[super class]);

            NSLog(@"%@",[super superclass]);

    分别是:当前类、当前类的父类、当前类、当前类的父类.

    总结[super message]

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

    2.从父类开始查找方法的实现.

    接下来博客我会介绍isKindOfClass和isMemberOfClass区别.(小插曲)

    比如你知道下面的结果值吗?

            BOOL res1  =  [[NSObject class] isKindOfClass:[NSObject class]];

            BOOL res2  =  [[NSObject class]isMemberOfClass:[NSObject class]];

            BOOL res3  =  [[GDStudent class]isKindOfClass:[GDStudent class]];

            BOOL res4  =  [[GDStudent class]isMemberOfClass:[GDStudent class]];

    介绍完这个面试题之后会再继续介绍runtime的其他知识点,来继续学习runtime

    如果觉得我写得对您有所帮助,请关注我,我会持续更新😄

    相关文章

      网友评论

          本文标题:从源码理解runtime之super、superclass知识点

          本文链接:https://www.haomeiwen.com/subject/rinzhltx.html