美文网首页
OC的self和super区别

OC的self和super区别

作者: 后浪普拉斯 | 来源:发表于2017-11-24 18:35 被阅读0次

我们在OC中经常遇见self和super,那接下来我看按照我们自己的思路,那么接下来我们看代码:

- (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"self class%@", NSStringFromClass([self class]));
    NSLog(@"super class%@", NSStringFromClass([super class]));
}

结果:

我们想象的结果是:
2017-11-24 14:14:19.173506+0800 objectClass_dyn[75423:12940896] self class ViewController
2017-11-24 14:14:19.173703+0800 objectClass_dyn[75423:12940896] super class UIViewController

因为我们理解的[super class]是调用父类的方法,应该是ViewController的父类UIViewController调用的方法.
但是世界的结果是:

2017-11-24 14:14:19.173506+0800 objectClass_dyn[75423:12940896] self class ViewController
2017-11-24 14:14:19.173703+0800 objectClass_dyn[75423:12940896] super class ViewController

此处的表情是:


不知所措.jpg

为什么会是这样呢?住不符合人类伦理道德啊!

那事实的真相只有一个,就是---

电脑抽风,那是不可能的。
那么真相就是:

self 是类的隐藏参数,指向所调用方法的类。那super是啥?super只是一个‘编译器指示符’,它和self指向相同的消息的接收者,所以不管是[self class]还是[super class],接收消息的对象都是ViewController。super 和self的不同之处是,super告诉编译器在调用class方法的同时要去父类调用方法,而不是从本类中。

此时你也许还有这样的疑问,对啊,super是去父类中调用了啊,为什么不是父类的对象。
当我们使用self调用方法的时候,先在本类的方法列表中查找,没有,才会去父类中寻找;但是使用super的时候,则直接从父类的方法列表中查找,然后调用这个方法。

那么接下来我们看一下:

使用clangg改造ViewController.m这个文件
clang -rewrite-objc ViewController.m

会发现上面的调用变成了:

NSLog((NSString *)&__NSConstantStringImpl__var_folders_14_p0_xgk8d7z746b5mfwnz78x80000gn_T_ ViewController_0aad65_mi_1, NSStringFromClass(((Class (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("class"))));

NSLog((NSString *)&__NSConstantStringImpl__var_folders_14_p0_xgk8d7z746b5mfwnz78x80000gn_T_ ViewController_0aad65_mi_2, NSStringFromClass(((Class (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("ViewController"))}, sel_registerName("class"))));

可以看到[self class]调用时,会被转化成objc_msgSend形式,而objc_msgSend的定义是:

void objc_msgSend(void /* id self, SEL op, ... */ )

我们把self作为第一个参数传入。
而我们在调用[super class]的时候,会被转化成objc_msgSendSuper形式,而objc_msgSendSuper的定义是:

void objc_msgSendSuper(void /* struct objc_super *super, SEL op, ... */ )

函数的第一个参数是一个名叫super的objc_super类型的结构体指针,那么objc_super 是什么样呢?

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 */
};
#endif

根据上面的宏的条件编译,实际上只存在两个参数receiver和super_class,前一个参数receiver类似于objc_msgSend函数的第一个参数self,要求是指定类的实例;第二个参数super_class,当前类的父类。

所以调用[self class]的时候,实际调用的objc_msgSend函数,第一个参数是ViewController这个类的实例,然后在ViewController这个类中找-(Class)class 这个方法,没找到去父类(UIViewController)找,也没有最后在NSObject找,而-(Class)class的实现就是返回self的类别,所以上述输出的结果为ViewController。

runtime中-(Class)class的实现:

-(Class)class{
    return object_getClass(self);
}

当调用[super class]时,会转换成objc_msgSendSuper函数,第一步是构建objc_super结构体,结构体的第一个成员便是ViewController的实例self,第二个成员变量是(id)class_getSuperclass(objc_getClass("ViewController")),便是ViewController的父类UIViewController。第二步是去UIViewController中寻找-(Class)class 这个函数,没有,然后去NSObject类中找,找到了,最后内部使用objc_msgSend(objc_super->receiver, @selector(class))去调用,此时和[self class]调用相同,还是返回ViewController。

总结:self和super 在调用的时候都是当前类或者类的实例去调用本身的方法或者父类的方法,用OC的语言来解释就是发送消息的对象都是当前的类或者当前类的实例。

简单的描述:
class A: B;
在A中:
[self class]; A或者A的实例对象调用本身的方法,调用方法的主体是类A或者A的对象。
[super class];A或者A的实例对象调用父类的方法,调用方法的主体是类A或者A的对象。
两个方法的调用的主体是没有变的,只是调用的方法是本身还是父类的区别。

相关文章

  • OC的self和super区别

    我们在OC中经常遇见self和super,那接下来我看按照我们自己的思路,那么接下来我们看代码: 结果: 因为我们...

  • Objective-C self与super的区别

    Objective-C self与super的区别 [self class] 和 [super class] 在当...

  • self、 superclass 、 super的区别

    self、 superclass 、 super的区别 self、 superclass 、 super self...

  • self和super的区别

    self和super的区别 self调用自己方法,super调用父类方法 self是类,super是预编译指令 [...

  • class

    1.[self class]和 [super class] self和super的区别: self是类的一个隐藏参...

  • 第3章 类和继承

    本章主要讲述了简单的类和继承的问题 在OC里面,继承主要注意几点即可: self于super的区别self代表当前...

  • 关于 self 和 super 在oc 中 的疑惑 与 分析

    关于 self 和 super 在oc 中 的疑惑 与 分析

  • self和super - OC

    self的应用场景: 用在类方法中使用:指代的是当前类 用在对象方法中使用:指代的是调用当前对象方法的那个对象 访...

  • Objective-C中的self和super

    发送消息给self和super @注意:OC中的self和JAVA中的self有些不同: 1> 在动态方法中,se...

  • self和super区别

    在objc中的类实现中经常看到这两个关键字”self”和”super”,但他们的区别表现在各个方面。以下面的代码为...

网友评论

      本文标题:OC的self和super区别

      本文链接:https://www.haomeiwen.com/subject/rhgxbxtx.html