self和super - ShenYj/ShenYj.github.io GitHub Wiki

self和super

  • self是类的隐藏参数,指向当前调用方法的这个类的实例
  • super本质上是一个编译器标识符,和self指向的是同一个消息接受者。不同的是super调用方式的时候,会告诉编译器去调用父类的方法而不是本类的方法。

self和super发送消息方法分别是objc_msgSendobjc_msgSendSuper

OBJC_EXPORT void
objc_msgSend(void /* id self, SEL op, ... */ )
    OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
OBJC_EXPORT void
objc_msgSendSuper(void /* struct objc_super *super, SEL op, ... */ )
    OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
    
/// Specifies the superclass of an instance. 
struct objc_super {
    /// Specifies an instance of a class.
    __unsafe_unretained _Nonnull id receiver;

    /// Specifies the particular superclass of the instance to message. 
#if !defined(__cplusplus)  &&  !__OBJC2__
    /* For compatibility with old objc-runtime.h header */
    __unsafe_unretained _Nonnull Class class;
#else
    __unsafe_unretained _Nonnull Class super_class;
#endif
    /* super_class is the first class to search */
};

self.class与super.class?

当在父类的方法列表中找到之后通过objc_super中的receiver去调用该方法的。
objc_super -> receiver就是此时的self,因此最终都为self.class,获取的都为类对象因此是一样的。

  • [self class]方法调用的本质是 发送消息,调用class的消息流程,拿到元类的类型,在这里是因为类已经加载到内存,所以在读取时是一个字符串类型,这个字符串类型是在map_imagesreadClass时已经加入表中
  • [super class]打印的结果与[self class]相同,原因是当前的super是一个关键字,在这里只调用objc_msgSendSuper2,其实他的消息接收者和[self class]是一模一样的

在转成 C++ 代码时显示的是 objc_msgSendSuper 函数,而实际运行时是 objc_msgSendSuper2, 首个参数的类型为 objc_super2,再传递消息时,会通过第二个参数(即当前类) 的superclass去查找方法

struct objc_super2 {
    id receiver;
    Class current_class;
};
ENTRY _objc_msgSendSuper2
UNWIND _objc_msgSendSuper2, NoFrame

ldp	p0, p16, [x0]		// p0 = real receiver, p16 = class
ldr	p16, [x16, #SUPERCLASS]	// p16 = class->superclass
CacheLookup NORMAL, _objc_msgSendSuper2

END_ENTRY _objc_msgSendSuper2
⚠️ **GitHub.com Fallback** ⚠️