天天看点

每天学一点Swift----面向对象下(二)

二.类的构造和析构

    1. 通过集成后,子类中不仅有父类中的存储属性,还有子类自己的存储属性。子类中的所有存储属性都必须在构造器中设置初始值,因此类的构造过程会相对比较复杂。

    2. 与构造器相反的是,Swift允许为类(枚举、结构体不允许)定义析构器:在实例临近销毁之前,系统会自动调用该实例的析构器(实例不允许主动调用自己的析构器)。Swift中析构器的本质就是一个名为deinit的函数。----这个函数不允许使用func关键字。

    3. 类的指定构造器和便利构造器:Swift为类提供了两种构造器来确保所有的实例存储属性都能得到初始值。这两个构造器是:指定构造器和便利构造器。

    4. 通常一个类至少要有一个指定构造器,指定构造器必须负责初始化类中所有的实例存储属性。指定构造器可通过父类链调用父类构造器初始化从父类继承得到的属性,还必须对自己的实例存储属性进行初始化。

    5. 便利构造器属于次要的、辅助性的构造器,类中可以没有便利构造器。便利构造器必须调用同一个类中的其他构造器来完成初始化。

    6. 如果程序需要在类中定义便利构造器,则需要在构造器的init之前添加convenience关键字。语法如下:

    convenience init(形参){ }

    7. 对比与便利构造器,不加任何特殊修饰符的构造器就是指定构造器。

    8. 只有类中才有便利构造器,结构体和枚举都不支持便利构造器。

    9. 举个栗子:

    class Apple

    {

    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)

    self.name = name

    }

    } 

    var app1 = Apple(n : "红富士", w : 1.2)

    var app2 = Apple(name : "花牛苹果", weight : 1.4)

    ----上面代码中包含了两个构造器,这两个构造器的外部形参名不同,这就是构造器重载。最后两行代码分别调用了两个构造器来创建了两个Apple实例。

    10. 类的构造器链----Swift对构造器之间的调用链制定了如下3条规则:

    (1)规则1:子类构造器必须调用直接父类的指定构造器。

    (2)规则2:便利构造器必须调用同一个类中的其他构造器

    (3)规则3:便利构造器调用的构造器链最终节点必须是指定构造器。

    上面的3条规则,总结一下就是:

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

    ----在构造器中调用其他构造器来执行构造的过程被称为构造器代理。

    11. 两段式构造----Swift类的构造需要两个阶段来完成;

    (1)第一阶段:先为存储属性分配内容,使用本类的构造器初始化由本类定义的存储属性;然后沿着构造器链向上,

    逐个调用各父类构造器初始化对应父类定义的存储属性;

    (2)第二阶段:从最顶层父类开始,沿着顶部构造器链向下,每个构造器都可以再次修改存储属性。

    ----  总结:向上调用,向下修改。

    12. 为了保证两段式构造顺利完成,Swift提供了4种安全检查:

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

    (2)安全检查二:制定构造器必须 ****先**** 向上调用父类构造器,然后才能对继承得到的属性赋值。原因很简单:如果先对继承得到的属性赋值,然后调用父类构造器,那么富类构造器会把指定构造器所赋的值覆盖掉。

    (3)安全检查三:便利构造器必选 ****先 *** 调用同一个类的其他构造器,然后才能对属性赋值。原因很简单:如果先对属性赋值,然后调用其他构造器,那么其他构造器会把便利构造器所赋的值覆盖掉。

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

    13. 不难发现,Swift中类的构造器规则是比较麻烦的,因此处理起来也比较容易出错。但如果程序显式地为所有实例

    存储属性都指定初始值,定义构造器时就会简单很多,而且可以直接利用系统默认的构造器。因此,一般建议为实例存储属性都指定初始值。

上一篇:每天学一点Swift----面向对象下(一)

下一篇:每天学一点Swift----面向对象下(三)