准备:
Person类、和Student类,其中 Person继承自NSObject, Student继承自Person。
@interface Person : NSObject
@end
@implementation Person
@end
============
@interface Student : Person
@end
@implementation Student
- (instancetype)init {
if (self = [super init]) {
NSLog(@"[self class] = %@", [self class]);
NSLog(@"[super class] = %@", [super class]);
NSLog(@"[self superclass] = %@", [self superclass]);
NSLog(@"[super superclass] = %@", [super superclass]);
}
return self;
}
@end
在main.m方法中创建一个Student的实例。
int main(int argc, const char * argv[]) {
@autoreleasepool {
Student *stu = [[Student alloc] init];
}
return 0;
}
打印结果:
2020-08-26 20:11:35.923899+0800 LearningRuntime[11990:229658] [self class] = Student
2020-08-26 20:11:35.925986+0800 LearningRuntime[11990:229658] [super class] = Student
2020-08-26 20:11:35.926719+0800 LearningRuntime[11990:229658] [self superclass] = Person
2020-08-26 20:11:35.927085+0800 LearningRuntime[11990:229658] [super superclass] = Person
如果结果正如你所料,就无需往下看了。(不错~)
分析
为什么打印的结果和我们预料的不一样呢?为了探个究竟,我们可以将OC代码转为C++,弄清楚这几句打印底层是如何实现的。
终端进入项目所在目录,执行以下命令,将OC转为C++代码.
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc Student.m
转化后结果:
static instancetype _I_Student_init(Student * self, SEL _cmd) {
if (self = ((Student *(*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Student"))}, sel_registerName("init"))) {
((Class (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("class"));
((Class (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Student"))}, sel_registerName("class"));
((Class (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("superclass"));
((Class (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Student"))}, sel_registerName("superclass"));
}
return self;
}
简化后核心代码如下:
static instancetype _I_Student_init(Student * self, SEL _cmd) {
if (self = objc_msgSendSuper({self, class_getSuperclass(objc_getClass("Student"))}, sel_registerName("init"))) {
// [self class]
objc_msgSend(self, sel_registerName("class");
// [super class]
objc_msgSendSuper({self, class_getSuperclass(objc_getClass("Student"))}, sel_registerName("class"));
// [self superclass]
objc_msgSend(self, sel_registerName("superclass"));
// [super superclass]
objc_msgSendSuper({self, class_getSuperclass(objc_getClass("Student"))}, sel_registerName("superclass"));
}
return self;
}
objc_msgSendSuper 的第一个参数是一个__rw_objc_super结构体实例,__rw_objc_super 的定义如下:
struct __rw_objc_super {
struct objc_object *object;
struct objc_object *superClass;
__rw_objc_super(struct objc_object *o, struct objc_object *s) : object(o), superClass(s) {}
};
由上可知:
[self class]分析:
[self class] 底层实际上转成了 objc_msgSend(self, sel_registerName("class"),利用消息机制给self发送了一条消息名为class的消息。消息机制会根据self的isa指针去其类对象(Student类对象)的方法列表找,找不到就会根据superclass指针往上找,最终会在NSObject类对象中找到并调用,我们看下NSObject中的方法实现。
// 类方法
+ (Class)class {
return self;
}
// 实例方法
- (Class)class {
return object_getClass(self); // 获取类对象
}
可以看到,NSObject对象方法class 实际上是调用了object_getClass(self); 最终返回实例的类对象(即 Student类对象)
-
[super class]分析:[super class]底层实际上转成了objc_msgSendSuper({self, class_getSuperclass(objc_getClass("Student"))}, sel_registerName("class")), 要理解这句话,需要看下objc_msgSendSuper函数的定义:/** * Sends a message with a simple return value to the superclass of an instance of a class. * * @param super A pointer to an \c objc_super data structure. Pass values identifying the * context the message was sent to, including the instance of the class that is to receive the * message and the superclass at which to start searching for the method implementation. * @param op A pointer of type SEL. Pass the selector of the method that will handle the message. * @param ... * A variable argument list containing the arguments to the method. * * @return The return value of the method identified by \e op. * * @see objc_msgSend */
OBJC_EXPORT id _Nullable objc_msgSendSuper(struct objc_super * _Nonnull super, SEL _Nonnull op, ...) OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
由方法定义可知: `objc_msgSendSuper`方法第一个参数为`objc_super` (`objc_super`中包含了`消息的接收者`和`开始搜索方法的类`),第二个参数为`消息名称`。 因此,`[super class]` 的消息接收者实际上还是`self`,只不过是从`superclass`(即`Person类对象`)开始搜索方法。我们知道`class`的实现是在`NSObject`中,所以最终也会调用`object_getClass(self)`方法获取类对象,此时的`self`就是消息的接收者(即`Student`). 所以最终获得类对象就是`Student类对象`。
3. `[self superclass]` 和 `[super superclass]` 分析:
理解了`self`和`super`的调用方法的区别,那这里只要知道了`superclass`方法底层是如何实现就没什么问题了. 在runtime源码中找到`NSObject.mm`文件,可以看到`superclass`方法的实现如下:
```cpp
// 类方法
+ (Class)superclass {
return self->superclass;
}
// 实例方法
- (Class)superclass {
return [self class]->superclass; // 获取当前类对象的父类
}
本例会调用实例方法,所以最终返回的是Student类对象的父类,即Person类对象。