美文网首页将来跳槽用
Objective-C self 与 super 的区别?

Objective-C self 与 super 的区别?

作者: 那是一阵清风_徐来 | 来源:发表于2019-01-12 00:59 被阅读0次
  • 案例
    新建一个类 Father
@interface Father : NSObject

@end
#import "Father.h"

@implementation Father

@end

新建一个类Son,继承Father

@interface Son : Father

@end
#import "Son.h"

@implementation Son

- (instancetype)init
{
    self = [super init];
    if (self) {
        
        NSLog(@"%@",NSStringFromClass(self.class));
        NSLog(@"%@",NSStringFromClass(super.class));
        
        NSLog(@"%@",self.class);
        NSLog(@"%@",super.class);
        /**
         2019-01-11 23:19:08.786280+0800 super与self[1501:29323] Son
         2019-01-11 23:19:08.786455+0800 super与self[1501:29323] Son
         
         2019-01-11 23:19:08.786575+0800 super与self[1501:29323] Son
         2019-01-11 23:19:08.786667+0800 super与self[1501:29323] Son
         
         */
    }
    return self;
}

@end

调用
Son *son = [[Son alloc] init];
输出结果:

2019-01-11 23:19:08.786280+0800 super与self[1501:29323] Son
2019-01-11 23:19:08.786455+0800 super与self[1501:29323] Son
--
2019-01-11 23:19:08.786575+0800 super与self[1501:29323] Son
2019-01-11 23:19:08.786667+0800 super与self[1501:29323] Son

  • 分析
  • self 是类的隐藏参数,指向当前调用方法的这个类的实例。
    而 super 是一个 Magic Keyword, 它本质是一个编译器标示符或者说是编译器指令,和 self 是指向的同一个消息接受者,也就是说【self本身就是一个强指针,而super不是, super本质上还是子类对象本身,而不是父类对象,super是告诉编译器,调用 class 这个方法时,要去父类的方法中去寻找,而不是本类里寻找】

上面的例子不管调用[self class]还是[super class],接受消息的对象都是当前 Son *xxx 这个对象。
而不同的是,super是告诉编译器,调用 class 这个方法时,要去父类的方法,而不是本类里的。
当使用 self 调用方法时,会从当前类的方法列表中开始找,如果没有,就从父类中再找;而当使用 super 时,则从父类的方法列表中开始找。然后调用父类的这个方法。

  • 利用runtime 底层原理分析
    把son.m文件转换成.cpp 文件【终端命令:$ clang -rewrite-objc Son.m

oc 代码

 NSLog(@"%@",NSStringFromClass(self.class));
 NSLog(@"%@",NSStringFromClass(super.class));

//新增下面两行代码
[super test];
[self test];

转换成.cpp 文件的代码

NSLog((NSString *)&__NSConstantStringImpl__var_folders_jw_5qlq_4rj54j7dqfnvnfn_lq40000gn_T_Son_08cc44_mi_0,NSStringFromClass(((Class (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("class"))));
        
NSLog((NSString *)&__NSConstantStringImpl__var_folders_jw_5qlq_4rj54j7dqfnvnfn_lq40000gn_T_Son_08cc44_mi_1,NSStringFromClass(((Class (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Son"))}, sel_registerName("class"))));

//[super test];
 ((void (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Son"))}, sel_registerName("test"));
       
//[self test];
 ((void (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("test"));
  • 分析
    不太熟悉runtime 同学,估计有不太明白,下面我简单的介绍一下
    runtime 又一个消息机制,我们一步步来举例分析【Person 为例】

  • 1、谈谈objc_msgSend

  • oc 创建一个person对象
    Person *p = [Person alloc];

  • 变形1
    Person *p = objc_msgSend([Person class], @selector(alloc));

    objc_msgSend(id _Nullable self, SEL _Nonnull op, ...) 这是runtime 方法里面的一个函数,表示发送一个消息机制,第 一个参数是消息接收者,第二个参数是调用的具体类方法的 selector】

  • 2、谈谈sel_registerName

  • 变形2
    Person *p = objc_msgSend(objc_getClass("Person"), sel_registerName("alloc"));
    sel_registerName(const char *str)向运行时系统注册一个方法名称,并生成SEL和方法名称的映射,最后返回SEL

  • 3、谈谈class_getSuperclass
    class_getSuperclass(Class _Nullable cls)指向该类的父类,如果该类已经是最顶层的根类(如NSObject或NSProxy),则super_class为NULL。

再来研究

[super test];
[self test];

唯一不同的就是:
{(id)self, (id)class_getSuperclass(objc_getClass("Son"))}
这个方法可以看出,调用test 的对象还是 son,只不过用父类指向一个子类对象,去父类方法里面去寻找 test 方法

  • 案例【自己去理解】
BOOL result1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];
BOOL result2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]];

BOOL result3 = [(id)[Son class] isKindOfClass:[Son class]];
BOOL result4 = [(id)[Son class] isMemberOfClass:[Son class]];
    
NSLog(@"result1 = %d ,result2 = %d,result3 = %d,result4 = %d",result1,result2,result3,result4);
// result1 = 1 ,result2 = 0,result3 = 0,result4 = 0

相关文章

网友评论

    本文标题:Objective-C self 与 super 的区别?

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