一、前提
查看OC编译后的代码:
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m
可以生成main.m编译后的文件,会生成main.cpp文件,就是oc转换成c的文件。我们可以通过这个cpp文件分析一些OC的特性。
二、消息机制obj_msgsend
1、通过几张图分析:
2、看个问题:
要分析这个问题,我们先看看这两个函数的伪代码:
截屏2021-07-03 上午11.43.35.png
不管是isMemberOfClass还是isKindOfClass,内部对调用者都会执行object_getClass,那说明调用者直接变成上一级,再进行比较,级数关系为:对象<类<元类。
根据这个,可以很容易推理出MJPerson的两个判断和[NSObject isMemberOfClass]都false。因为object_getClass(MJPerson)-元类和[MJPerson class]-类,不在一个级别上。
最后看看[NSObject isKindOfClass:[NSObject class]]。感觉这两个也不在一个级别,为什么就是真呢?
截屏2021-07-03 上午11.52.17.png
结合上图和isKindOfClass的实现,任何继承于NSObject的对象或类,如obj,如果使用[obj isKindOfClass:[NSObject class]]都是真,因为isKindOfClass会不断找父类。如上图,不断找父类,不管类或元类,都会最终找到NSObject。
三、Super
1、先看问题:
上图的MJStudent的父类为MJPerson,测试代码是在MJStudent中。上面两个还好理解。我们主要分析下[super class]和[super superclass]。
我们知道class和superclass方法都是在NSObject里面的,大概实现如下:
截屏2021-07-03 上午11.34.34.png
看到实现,我们只要分析调用者self是谁,就能得到结论。那么super的调用者self是谁呢?
其实super的调用者还是本类,本案例是在MJStudent中进行测试,所以super的调用者就是MJStudent。super只是让MJStudent的消息查找从父类开始,直接跳过本类的消息查找。所以答案很明显了。
网友评论