学习runtime中的self和super
我们先来看已到习题:
下面代码输出的会是什么?这个类名叫test,继承自NSObjec
图1我只能肯定的告诉大家,这里输出的都是test.
self是类的隐藏参数,指向当前调用方法的类的实例,而super是一个关键字,是一个系统标识符,这里的self调用class方法会先从本类找,如果找不到就去父类找,而[super class]是在调用方法前告诉编译器在调用这个方法之前先要调用父类的class方法.不管上面[self class] 还是[super class]接收消息的对象都是test.
那我们如何验证啦?
懵逼好吧那我现在就给大家分析一下
我们可以使用clang命令来重写命令:
$ clang -rewrite-objc test.m
然后我们发现我们刚才的打印转换成了这样
NSLog((NSString *)&__NSConstantStringImpl__var_folders_gm_0jk35cwn1d3326x0061qym280000gn_T_main_a5cecc_mi_0, NSStringFromClass(((Class (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("class"))));
NSLog((NSString *)&__NSConstantStringImpl__var_folders_gm_0jk35cwn1d3326x0061qym280000gn_T_main_a5cecc_mi_1, NSStringFromClass(((Class (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){ (id)self, (id)class_getSuperclass(objc_getClass("test")) }, sel_registerName("class"))));
先看第一个我们都知道oc语言的消息机制所以我们看编译后的代码,都从objc_mgsSend看起.我们明显的看到[self class]调用时objc_msgSend()函数的第一个参数是self,而[super class]则调用的是objc_msgSendSuper()函数,第一个参数是一个结构体
objc_super第一个消息接受者类似于上一个的self,第二个是记录当前类的父类是什么.
所以当调用[self class]时,转化为objc_msgSend时,第一个参数是test的实例对象,然后在test这个类里面查找class这个方法,然后就去父类查找.所以我们看到第一个输出的是test
第二个调用[super class],转化成objc_msgSendSuper()函数,第一个参数是一个结构体,第一个成员是self,第二个成员是(id)class_getSuperclass(objc_getClass("test")也就是NSObect,实际上该函数应该输出NSObject,但是通过第二步先去NSObjec中找class方法,找到了,然后调用这个方法时:objc_msgSend(objc_super->receiver, @selector(class))又被转换成和第一种调用相同.所以输出的是test.
好了今天的学习就到这了,要明确super和self的不同.
总结,super是关键字,会告诉编译器,在调用改方法前,先去调用父类的方法.
而self会直接转换成objc_msgSend消息机制,接受者是self.而super会转化成objc_msgSuperSend(),单最终的耗时会转换成与[self class]相同的调用.
谢谢
本人联系方式:qq:513961360
email:513961360@qq.com
也可以加我们的qq群希望能与朋友们一起聊天和学习.群里还有很多iOS开发者,帮助我们解决问题,并且同时学习.
qq群号:580284575