Swift类的构造过程

作者: dongwenbo | 来源:发表于2016-12-27 15:01 被阅读55次

    Swift类的存储型属性必须在构造过程完成后有值,Swift为类提供了两种构造器——指定构造器、便利构造器

    指定构造器
     init(参数表){
        构造过程
     }
    

    指定构造器先完成自身类属性值的初始化,再调用父类指定构造器完成父类属性值初始化,一个类可以有多个指定构造器,但至少要有一个(继承的,默认的都算)。在指定构造器中不可以调用本类其他构造器,只能向上代理

    便利构造器
      convenience init(参数表){
        构造过程
      }
    

    便利构造器必须调用本类其他构造器完成初始化,而且最终必须导致本类一个指定构造器被调用,便利构造器不可以直接调用父类构造器,只能横向代理

    总结为三条规则:

    1、指定构造器必须调用其直接父类(如果有)的指定构造器(先初始化自己的属性,然后调用父类的构造器初始化父类的属性)
    2、便利构造器必须调用本类中其他构造器
    3、便利构造器最终需要导致一个指定构造器调用

    指定构造器必须总是向上代理,便利构造器必须总是横向代理

    构造过程

    两段式构造过程

    第一阶段:

    1、构造器被调用
    2、分配内存,未初始化
    3、指定构造器为本类存储属性赋初值,本类存储属性完成初始化
    4、向上调用父类指定构造器,重复类似3,4过程,直到顶部类
    5、自下而上所有存储属性完成初始化,第一阶段完成


    第一阶段
    第二阶段:

    1、从顶部往下,每一层的指定构造器都有机会进一步定制本类实例,此时构造器可以访问self,修改属性,调用实例方法等,也就是说在未完全初始化时,实例是不可以使用的
    2、最终,任意构造器链中的便利构造器都可以定制实例和使用self


    第二阶段
    编译器进行四种安全检查保证上述构造准确进行
    • 指定构造器先初始化本类的存储属性后,才可以向上代理给父类的指定构造器
    • 指定构造器必须要在调用父类的指定构造器后,才可以为继承来的属性赋新值,不然就被父类初始值覆盖
    • 便利构造器必须先调用本类其他构造器,才能为属性赋新值,不然会被初始值覆盖
    • 构造器在第一阶段完成前,不能调用实例方法,不能读取实例属性值,不能引用self作为一个值

    默认构造器

    默认构造器就是不带参数的构造器,当类中没有提供任何构造器时(继承来的也算),属性都有默认值时, 编译器会提供一个默认构造器

    class ABC{
        var a:Int = 1
        var b:Int = 2
        var c:Int = 3
    }
    
    var abc = ABC()//编译器会提供一个默认的构造器
    print(abc.a,abc.b,abc.c)
    
    class A {
        init() {
        }
    }
    

    没有问题,默认就是这样,我们写了和默认编译器一样的东西,也就是说我们可以自己定义指定型的默认构造器

    class A {
        convenience init() {
            self.init()
        }
    }
    

    编译报init()重定义,便利构造器不会阻止编译器自动生成默认构造器,和默认构造器重名,所以报错

    class A {
        var a:Int
        init(a:Int) {
            self.a = a
        }
        convenience init() {
            self.init()
        }
    }
    

    这段代码编译不报错,运行阶段调用init()进入死循环,我们有init(a:int),所以编译器不会自动生成默认构造器,然后我们写convenience init(),也不会报错,奇怪的是构造过程并不满足三条规则中的规则三,因为已经没有了指定的默认构造器,然而编译器不报错,运行却进入死循环,妥妥的编译器bug

    子类中访问父类的属性,用selfsuper都行

    相关文章

      网友评论

        本文标题:Swift类的构造过程

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