美文网首页iOS奋斗iOS学习iOS调试技巧
一万小时定律的遗憾之Objective-C的self与super

一万小时定律的遗憾之Objective-C的self与super

作者: 仁伯 | 来源:发表于2016-12-24 17:09 被阅读2316次

    Malcolm T.Gladwell说:“人们眼中的天才之所以卓越非凡,并非天资超人一等,而是付出了持续不断的努力。1万小时的锤炼是任何人从平凡变成超凡的必要条件。”

    对于一万小时定律,我是深信不疑的,然而真的尝试做着的时候,才发现一万小时,对于天资愚钝的我还远远不够。

    学习Objective-C已近两年,每天的工作学习的平均时间也控制在十个小时以上,渐渐地一直以为自己对其机制及语法有了一定认识,然而看到别人对两个编程中最常用到关键字self、super的理解的时候,实在羞愧,深感自己对平日使用的东西了解还太少太少。

    super.jpg

    正文

    当然,这一切都要从一个Model和一个网上的笔试题说起:

    1、一个Model
    #import <Foundation/Foundation.h>
    
    @interface EVNHelper : NSObject
    - (instancetype)init;
    @end
    
    #import "EVNHelper.h"
    
    @implementation EVNHelper
    
    - (instancetype)init
    {
        self = [super init];// ???
        if (self)
        {
           // other init code 
        }
        return self;
    }
    @end
    
    2、 一个笔试题
    - (instancetype)init
    {
        self = [super init]; 
        if (self)
        {
            NSLog(@"self className is %@", NSStringFromClass([self class]));
            NSLog(@"super  className is %@", NSStringFromClass([super class]));
    
            NSLog(@"self superclass  className is %@", NSStringFromClass([self superclass]));
            NSLog(@"super superclass  className is %@", NSStringFromClass([super superclass]));
        }
        return self;
    }
    @end
    
    输出:
        2016-12-24 16:04:32.600 Demo[6009:1006834] self className is EVNHepler
        2016-12-24 16:04:32.601 Demo[6009:1006834] super  className is EVNHepler
        2016-12-24 16:04:32.601 Demo[6009:1006834] self superclass  className is NSObject
        2016-12-24 16:04:32.602 Demo[6009:1006834] super superclass  className is NSObject
    

    对应的问题也来了:

    1、子类初始化为什么要写self = [super init],意义?
    2、为什么[self class]和 [super class];[self superclass]和[super superclass]输出相同?

    可到底self和super是什么呢?(由于对runtime懂得太少,怕误人子弟,暂不扯底层代码,只说自己能看到的)

    • self
      之前我的理解,self是对象指针,指向当前类的实例对象。其实这种理解是不准确的,因为在静态方法self 依然可以使用(如下代码),这怎么解释呢!
    + (void)helperMethodA
    {
        [self helperMethodB];
    }
    + (void)helperMethodB
    {
        NSLog(@"asdfasdfasd");
    }
    

    带着这份好奇,最终我在NSObject协议中找到了self,原来self是返回instancetype类型的代理方法,但又有些奇怪,我们在自定义子类的时候并没有实现这个方法,我认为self的功能,OC已经帮我们实现,只是我们看不到而已。这样就明确了,self最终返回的结果就是instancetype类型的东西,它是动态类型,最终运行时才会确定,实例方法返回实例类型、静态方法返回的是Class。

    #include <objc/objc.h>
    #include <objc/NSObjCRuntime.h>
    
    @class NSString, NSMethodSignature, NSInvocation;
    @protocol NSObject
    
    - (BOOL)isEqual:(id)object;
    @property (readonly) NSUInteger hash;
    @property (readonly) Class superclass;
    ......
    - (Class)class OBJC_SWIFT_UNAVAILABLE("use 'anObject.dynamicType' instead");
    - (instancetype)self;
    ......
    @end
    
    
    • super
      在Foundation框架中,super是找不到的,该关键字应该是比self更为奇特的东西。虽然找不到super,但我们可以看到结构体objc_super,在官方解释中我们能看到一些端倪。

    objc_super: The compiler generates an objc_super data structure when it encounters the super keyword as the receiver of a message. It specifies the class definition of the particular superclass that should be messaged.

    大致意思就是,当遇到super关键字时,编译器会生成一个objc_super结构体,作为消息的接收者,objc_super结构体使得接收消息的父类的定义被明确化。
    所以,super的含义应该是一种编译指令,它的作用用来给父类发送消息,并返回消息响应的结果。

    #include <objc/objc.h>
    #include <objc/runtime.h>
    
    #pragma GCC system_header
    
    #ifndef OBJC_SUPER
    #define OBJC_SUPER
    
    /// Specifies the superclass of an instance. 
    struct objc_super {
        /// Specifies an instance of a class.
        __unsafe_unretained id receiver;
        /// Specifies the particular superclass of the instance to message. 
    #if !defined(__cplusplus)  &&  !__OBJC2__
        __unsafe_unretained Class class;
    #else
        __unsafe_unretained Class super_class;
    #endif
    };
    

    知悉了这两点,上面的两个问题也就迎刃而解了。

    解答:

    问题一:self = [super init]是面向对象思想的一种体现,意义就是,利用父类的init方法为子类初始化父类的公有属性。
    问题二:理解这个先要明确alloc和init的区别,alloc为对象开辟内存,init是对象初始化,所以,[super init] 是初始化在子类上的,super发出消息的主体对象是子类,和self是同一个对象。 class方法和self类似是NSObject协议中的代理方法,我认为class的功能,OC也已经帮我们实现在每个子类中,只是我们看不到而已,所以不管是super还是self发出的class消息,执行的时候,都在子类中,返回的都是子类。

    参考:

    相关文章

      网友评论

        本文标题:一万小时定律的遗憾之Objective-C的self与super

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