iOS开发一道super面试题引发的思考

今天,有小伙伴偶然转发了一道面试题:

运行结果是:Screen  LEDScreen  LEDScreen

对此,我们都知道第一次调用是Screen类的实例对象screen1调用了Screen类的对象方法helloScreen

第二次是子类LEDScreen的实例对象screen2调用了子类的helloScreen对象方法,子类这个方法中通过super指针又调用了父类方法,所以这一次方法调用者仍然是screen2,所以self class自然也就是LEDScreen

第三次调用自然不用说,大家都懂,结果是LEDScreen

这里有个注意的地方:子类方法中[super helloScreen]仅仅是告诉调用者去父类中寻找helloScreen这个方法,并不是父类调用helloScreen方法.

问题引入:虽然一直听别人这么说,但总想一探究竟,为什么[super helloScreen]时,父类中的[self class]中的self仍然是子类LEDScreen对象

要解决问题当然就要从源码入手,从底层窥探[super helloScreen]到底做了哪些事

1.首先,我们自己新建一个文件TestC.h和TestC.m,如图:


然后进入终端,切换到该文件目录下,键入:xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc TestC.m -o main-arm64.cpp

运行过后生成一个.cpp文件,这个文件里就是TestC编译后的c++代码.

2.打开这个文件,搜索关键字helloScreen相关的代码块,可以定位到这里,因括号太多不太容易看出结构,为了方便理解,我把这一串代码格式调整成了这样:

从中可以看出各个方法对应的底层c++实现.现在最重要的就是看绿色框中的[super helloScreen]到底做了什么事,分析图:


从中可以看出,实际上[super helloScreen]在底层变成了objc_msgSendSuper方法,这个方法需要两个参数,一个参数是__rw_objc_super,另一个是SEL.下面的代码中看出__rw_objc_super是一个结构体,第一个成员是当前的self指针(LEDScreen),第二个成员是根据LEDScreen获取它的父类.

但是这个objc_msgSendSuper拿到__rw_objc_super干什么去了呢?这里我们可以查看runtime源码.因为message.m并不开源,我们只能从message.h里查看相关信息了,如图:


虽然看不到.m中objc_msgSendSuper的具体实现,但这里已经大致说明这几个参数将来的用场了.

猜你喜欢

转载自blog.csdn.net/qq_31186665/article/details/80370718
今日推荐