小斑iOS DeveloperiOS学习笔记

Swift类的构造过程

2016-12-27  本文已影响55人  dongwenbo

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

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

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

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

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

总结为三条规则:

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

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

构造过程

两段式构造过程

第一阶段:

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


第一阶段
第二阶段:

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

上一篇下一篇

猜你喜欢

热点阅读