ObjC Runtime简析 -- super和superclass

请注意,本文编写于 226 天前,最后修改于 165 天前,其中某些信息可能已经过时。

这一个经典的面试题,Student是Person的一个子类,在子类Student的init方法中调用4个方法并打印结果。

经典面试题
经典面试题
objc_msgSend(self, sel_registerName("class"))
objc_msgSend(self, sel_registerName("superclass"))
objc_msgSendSuper({self, class_getSuperclass(objc_getClass("Student"))}, sel_registerName("class"))
objc_msgSendSuper({(id)self, (id)class_getSuperclass(objc_getClass("Student"))}, sel_registerName("superclass"))

将这个Student.m转换为cpp文件查看其底层的方法调用的到如下调用:

[self class]: objc_msgSend(self, sel_registerName("class"))
[self superclass]: objc_msgSend(self, sel_registerName("superclass"))
[super class]: objc_msgSendSuper({self, class_getSuperclass(objc_getClass("Student"))}, sel_registerName("class"))
[super superclass]: objc_msgSendSuper({self, class_getSuperclass(objc_getClass("Student"))}, sel_registerName("superclass"))

我们看到当对self进行消息发送的时候底层是调用了runtime的objc_msgSend方法,而对super进行消息发送的时候底层是调用了objc_getSuperClass

objc_msgSend方法我们都熟悉了,将会从self开始查找class方法和superclass方法的实现,调用打印Student和Person。

而对super发送消息,底层将会调用objc_msgSendSuper函数,这个函数有两个参数,第一个是一个结构,第二个是方法选择器。结构体有两个成员:

objc_msgSendSuper
objc_msgSendSuper

第一个是消息接受者,第二个参数我们通过注释可以看出,表示函数从哪里开始查找法方法。而这里传递的是class_getSuperclass(objc_getClass("Student"))表示Student的父类,也就是Person类开始查找方法。查找的方法是classsuperclass,而这两个方法存在于NSObject中,查找到了之后依然使用objc_msgSendSuper第一个参数结构体的第一个成员接收消息。消息接受者是self,所以依然调用selfclass方法和superclass

所以最终[super class][super superclass]打印的依然是Student和Person。

总结

对super发消息底层调用的是objc_msgSendSuper方法,它有两个参数,第一个是一个结构,第二个是方法选择器。本质上所做的操作是从当前类的父类开始查找方法,而消息的接受者依然是self,也就是当前类,所以最后还是[self xxxx]

Comments

添加新评论