self和super小结

关键区分:

1.self是类隐藏参数,super是预编译指令
2.self 调用本类方法,super 调用父类方法
3.(面试相关)【self class】和【super class】输出是一样
为什么会这样呢,往下看:

self和super底层实现原理:

self 调用方法时,查找方法列表 是从本类为起点出发的;而 super ,则从父类的方法列表中开始找,然后调用父类的这个方法。(这句是关键)

他俩都是消息发送

1.self 调用时, objc_msgSend 函数: id objc_msgSend(id theReceiver, SEL theSelector, ...)。第 一个参数是消息接收者,第二个参数是调用的具体类方法的 selector,后面是 selector 方法的可变参数。

2.super 调用时,会使用 objc_msgSendSuper 函数:id objc_msgSendSuper(struct objc_super *super, SEL op, ...)第一个参数是个objc_super的结构体,第二个参数还是类似上面的类方法的selector

struct objc_super {
  id receiver;         //即消息的实际接收者。 
  Class superClass;    //指针当前类的父类。
};

当编译器遇到 [super class:] 时,开始做这几个事:

  1. 构 建 objc_super 的结构体,这个结构体的第一个成员变量 receiver 就是 子类,和 self 相同。而第二个成员变量 superClass 就是指父类
    调用 objc_msgSendSuper(super->receiver, @selector(class)) 的方法,将这个结构体和 class 的 SEL 传递过去。

  2. 函数里面在做的事情类似这样:从 objc_super 结构体指向的 superClass 的方法列表开始找class 的 selector,找到后再以 objc_super->receiver 去调用这个 selector

举个🌰:

创建三个有继承关系的类:ClassA->ClassB->ClassC(父->子)

1.png

1.classA 、classB、classC 分别都重写了自己的class方法

-(Class)class{
    return [ClassC class];
}

打印结果:

2.png
  1. 仅classC实现自己的-(Class)class方法结果如下
    3.png

    总结:
    1).superClass 就是父类
    2).[self class]和 [super class]查找方法的起始位置不同,但调用者是一样的。

为什要写self = [super init]?

因为在Xcode中,你输入init然后tab就会帮你补全这个方法,以至于我一直都忽略了为什么在[super init]之后还要赋值给self,然后进行判断,其实这和类簇有关系,我们不能保证init的内存和alloc出来的内存是同一块内存,像NSString在alloc和init之后的对象分别是NSPlaceholderString和__NSCFConstantString*造成[super init]之后的内存被改变,所以在[super init]之后是nil,因此我们不能保证alloc和init的是同一块内存,加上这样的判断是为了提高容错性,如果init成功就返回对象,否则返回nil.

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。