前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >A interesting inheritance question between self and super

A interesting inheritance question between self and super

作者头像
Mitchell
发布2018-09-30 09:38:44
3750
发布2018-09-30 09:38:44
举报
文章被收录于专栏:西二旗一哥
  • Here is a inheritance chain relationship: NSObject -> RootCls -> SubCls
  • Think About a question? What will the followed code to be printed?
代码语言:javascript
复制
@implementation SubCls
- (void)print {
    NSLog(@"%@",[self class]);
    NSLog(@"%@",[self superclass]);
    NSLog(@"%@",[super class]);
    NSLog(@"%@",[super superclass]);
}
@end
  • Ordinary, the wrong answer may look like this:
代码语言:javascript
复制
SubCls  
RootCls  
RootCls  
NSObject  
  • While the truth is:
代码语言:javascript
复制
SubCls  
RootCls  
SubCls  
RootCls  
  • Hard to believe!Then let's look at the c plus plus method which transform from objective-c codes:
代码语言:javascript
复制
static void _I_SubCls_print(SubCls * self, SEL _cmd) {  
    NSLog((NSString *)&__NSConstantStringImpl__var_folders_w4_kn5xrqqn04bcyjv2pkqzv1qr0000gn_T_SubCls_0dc642_mi_0,((Class (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("class")));
    NSLog((NSString *)&__NSConstantStringImpl__var_folders_w4_kn5xrqqn04bcyjv2pkqzv1qr0000gn_T_SubCls_0dc642_mi_1,((Class (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("superclass")));
    NSLog((NSString *)&__NSConstantStringImpl__var_folders_w4_kn5xrqqn04bcyjv2pkqzv1qr0000gn_T_SubCls_0dc642_mi_2,((Class (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("SubCls"))}, sel_registerName("class")));
    NSLog((NSString *)&__NSConstantStringImpl__var_folders_w4_kn5xrqqn04bcyjv2pkqzv1qr0000gn_T_SubCls_0dc642_mi_3,((Class (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("SubCls"))}, sel_registerName("superclass")));
}
//The definition of struct `__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) {} 
};
//The definition of struct `objc_object`
struct objc_object {  
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;
};
  • As you can see that if we call class and superclass to self, it will call objc_msgSend method. While if we call these method with super it will call objc_msgSendSuper method, so we can have a depth look at this method:
代码语言:javascript
复制
//It has two params, one is a struct with type `objc_super *`, and the other is a `SEL`
objc_msgSendSuper(struct objc_super * _Nonnull super, SEL _Nonnull op, ...)  
//We can also see the `objc_super *` struct, it contain a receiver and a Class instance.
struct objc_super {  
    __unsafe_unretained _Nonnull id receiver;
#if !defined(__cplusplus)  &&  !__OBJC2__
    __unsafe_unretained _Nonnull Class class;
#else
    __unsafe_unretained _Nonnull Class super_class;
#endif
};
#endif
  • It's not hard to see that we can see struct __rw_objc_super as objc_super and the final code will be like this:
代码语言:javascript
复制
objc_msgSendSuper((objc_super){self,class_getSuperclass(objc_getClass("SubCls"))},sel_registerName("class"))  
objc_msgSendSuper((objc_super){self,class_getSuperclass(objc_getClass("SubCls"))},sel_registerName("superclass"))  
  • Aditionaly, let's look at the assemble code with objc_msgSendSuper:
代码语言:javascript
复制
/********************************************************************
 * id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
 *
 * struct objc_super {
 *     id receiver;
 *     Class cls;    // the class to search
 * } ********************************************************************/
    ENTRY _objc_msgSendSuper
    MESSENGER_START
    ldr r9, [r0, #CLASS]    // r9 = struct super->class
    CacheLookup NORMAL
    // cache hit, IMP in r12, eq already set for nonstret forwarding
    ldr r0, [r0, #RECEIVER] // load real receiver
    MESSENGER_END_FAST
    bx  r12         // call imp
    CacheLookup2 NORMAL
    // cache miss
    ldr r9, [r0, #CLASS]    // r9 = struct super->class
    ldr r0, [r0, #RECEIVER] // load real receiver
    MESSENGER_END_SLOW
    b   __objc_msgSend_uncached
    END_ENTRY _objc_msgSendSuper
  • Then, let's have a look at the underlying principle in the NSObject.mm which you can download from the apple open source:
代码语言:javascript
复制
+ (Class)class {
    return self;
}
- (Class)class {
    return object_getClass(self);
}
+ (Class)superclass {
    return self->superclass;
}
- (Class)superclass {
    return [self class]->superclass;
}
  • Come to the conclusion, call method class and superclass will make the RootCls receive the class and superClass method, while it don't rewrite the method so it will call the NSObject's method,and it will have the same result as self.
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档