Objective-C Super的理解

1.Super的理解

先看下面的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@interface Father : NSObject
@end
@implementation Father
@end

@interface Son : Father
@end
@implementation Son
- (id)init
{
    self = [super init];
    if (self)
    {
        NSLog(@"%@", NSStringFromClass([self class]));
        NSLog(@"%@", NSStringFromClass([super class]));
    }
    
    return self;
}
@end

输出的结果:

1
2
Son
Son

根据[super class]表面的意思我们很容易理解输出应该为Father。真是的情况是这样的,super只是一个编译器指示符,当使用superself发送消息的时候,消息的接收者都是self,本质上通过self发送消息会转化成objc_msgSend方法的调用,objc_msgSend负责从当前类的方法列表开始查询,而通过super发送消息会转化成objc_msgSendSuper方法的调用,objc_msgSendSuper是从当前类的父类的方法列表开始查询方法的。 objc_msgSend定义如下:

1
id objc_msgSend(id receiver, SEL op, ...)

self默认为objc_msgSend方法的第一个参数,所以[self class]的接收者为self,而class方法在NSObject基类中定义,返回消息接收者receiver的。 objc_msgSendSuper定义如下:

1
id objc_msgSendSuper(struct objc_super *super, SEL op, ...)

第一个参数是个objc_super的结构体,定义如下:

1
2
3
4
struct objc_super {
    id receiver; 
    Class superClass;
};

可以看到这个结构体包含了两个成员,一个是receiver,这个类似上面objc_msgSend的第一个参数receiver,第二个成员是记录这个类的父类是什么,构建objc_super的时候第一个参数赋值为selfsuperClass赋值为self的父类指针。 最上面的例子中[super class]具体执行过程如下: 1.构建objc_super的结构体,此时这个结构体的第一个成员变量receiver就是Son的实例,和self相同。而第二个成员变量superClass就是指类Father。 2.调用objc_msgSendSuper方法,将objc_super结构体和classsel传递过去。函数里面在做的事情类似这样:从objc_super结构体指向的superClass的方法列表开始找classselector,找到后再以objc_super->receiver去调用这个selector,可能也会使用objc_msgSend这个函数,不过此时的第一个参数receiver就是objc_super->receiver,第二个参数是从objc_super->superClass中找到的selector