构造器(二)----指定构造器、便利构造器

在上一篇博客中简单介绍了构造器基础层面的知识构造器(一),下面我们深入的学习类的构造器应用。

在Swift中类一共有两种构造器:

  • 指定构造器
  • 便利构造器

什么是指定构造器,有什么作用?

我个人的理解为在类中没有加任何关键字的构造器称为指定构造器,作用为初始化类中所有的实例存储属性

init()
{
   ...
}

什么是便利构造器,有什么作用?

我个人理解为在类中(只能在类中,结构体和枚举里面是没有的)加上convenience关键字的构造器为便利构造器,作用为辅助性调用指定构造器进行一系列的工作。感觉体现了在Object-C中的代理模式。

 convenience init()
 {
     ...
 //注意这里必须调用同一类的其他构造器,这里调用的可以是其他便利构造器或者是指定构造器
 }

综合的看一个励志吧,请原谅程序员的屌丝:

         class Man
    {
    var say:String
     init(say:String)
    {
    self.say=say
    }

    convenience init(Say:String)
    {
        self.init(say:Say)

    }
}
    var man1=Man(say: "我喜欢你!")
    print(man1.say)
    var man2=Man(Say: "啊,不,我不喜欢你!我爱你!")
    print(man2.say)

构造器的调用链遵守三条规则

  • 子类构造器必须调用直接父类的指定构造器
  • 便利构造器必须调用同一类中的其他构造器
  • 便利构造器调用的构造器的终点必须是指定构造器

类构造的两个阶段:

第一阶段:

  1. 程序调用子类的某个构造器

  2. 为实例分配内存, 此时实例的内存还没有被初始化

  3. 指定构造器确保子类定义的所有实例存储属性都已被赋初值

  4. 指定构造器将调用父类的构造器, 完成父类定义的实例存储属性的初始化

  5. 沿着调用父类构造器的构造器链一直往上执行, 直到到达构造器链的最顶部

第二阶段:

  1. 沿着继承树往下, 构造器此时可以修改实例属性和访问self, 甚至可以调用实例方法

  2. 最后, 构造器链中的便利构造器都有机会定制实例和使用self

Swift安全检查

  • 安全检查1:指定构造器必须先初始化当前类中定义的实例存储属性, 然后才能向上调用父类构造器

  • 安全检查2:指定构造器必须向上调用父类构造器, 然后才能对继承得到的属性赋值

  • 安全检查3:便利构造器必须先调用同一个类的其他构造器, 然后才能对属性赋值

  • 安全检查4:构造器在第一阶段完成之前, 不能调用实例方法, 不能读取实例属性

    class Person {
    
    var name: String!
    var weight: Double
    
    // 定义指定构造器
    init(name: String, weight: Double) {
        self.name = name
        self.weight = weight
    }
    
    // 定义便利构造器(使用convenience修饰)
    convenience init(n name: String, w weight: Double) {
        self.init(name: name, weight: weight)
    }
    

    }

    class Man: Person {
    
    var sex: String!
    
    init(sex: String, name: String, weight: Double) {
    // print(super.name) 不能再父类初始化之前调用父类中的属性
    super.init(name: name, weight: weight)
    super.name = "lala"
    print(self.name)
    // print(self.sex) 不能在本类中的属性没有进行初始化的时候进行调用
    // 会出现:fatal error: unexpectedly found nil while unwrapping an Optional value错误
    self.sex = sex
    print(self.sex)
    }
    
    convenience init(s sex: String, n name: String, weight: Double) {
    
    // 在调用其他构造器之前, 不能访问或修改任何实例存储属性
    // print(self.name) 错误
    // super.name = name 错误
    self.init(sex: sex, name: name, weight: weight)
    }
    }
    var man = Man(sex: "男", name: "Rinpe", weight: 62.0)
    

你可能感兴趣的:(构造器,便利构造器,类构造器,指定构造器)