先上一段代码
在上述代码中,Dog是继承自NSObject。但是在Dog的初始化方法当中打印super class出现的竟然是Dog
因为OC是运行时机制,在运行时,self class相当于调用了runtime中给某一个对象发消息的C函数。给对象发消息有四种方式
1.objc_msgSend
2.objc_msgSend_stret
3.objc_msgSendSuper
4.objc_msgSendSuper_stret
在子类中调用self class方法时相当于调用了objc_msgSend这个方法。
第一个参数是消息接收者,第二个参数是调用的具体类方法的selector,后面是selector方法的可变参数。我们先不管这个可变参数,以 [self setName:]为例,编译器会替换成调用objc_msgSend的函数调用,其中theReceiver是self,theSelector是 @selector(setName:),这个selector是从当前self的class的方法列表开始找的setName,当找到后把对应的 selector传递过去。
在子类当中调用super class时相当于调用了objc_msgSendSuper方法。
看下objc_msgSendSuper的函数定义:
id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
第一个参数是个objc_super的结构体,第二个参数还是类似上面的类方法的selector,先看下objc_super这个结构体是什么东西:
struct objc_super {
id receiver;
Class superClass;
};
当使用
[self class]
时,这时的self是Dog,在使用objc_msgSend时,第一个参数是receiver也就是self,也是 Dog* dog这个实例。第二个参数,要先找到class这个方法的selector,先从Dog这个类开始找,没有,然后到Dog的父类 Father中去找,也没有,再去Father的父类NSObject去找,一层一层向上找之后,在NSObject的类中发现这个class方法,而 NSObject的这个class方法,就是返回receiver的类别,所以这里输出Dog。
当使用
[super class]
时,这时要转换成objc_msgSendSuper的方法。先构造objc_super的结构体吧,第一个成员变量就是self, 第二个成员变量是Father,然后要找class这个selector,先去superClass也就是Father中去找,没有,然后去Father 的父类中去找,结果还是在NSObject中找到了。然后内部使用函数objc_msgSend(objc_super->receiver, @selector(class)) 去调用,此时已经和我们用
[self class]
调用时相同了,此时的receiver还是Dog* dog,所以这里返回的也是Dog。