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

来源:互联网 发布:配电柜报价软件 编辑:程序博客网 时间:2024/05/21 08:38

.类的构造和析构()

    1. Swift中,子类不会自动继承父类的构造器,只有满足如下规则时,子类才会自动继承父类的构造器:

    1)规则1:如果子类没有提供任何指定构造器,那么它将自动继承父类的所有指定构造器

    2)规则2:如果子类实现了父类所有的指定构造器,无论是通过规则1继承实现的,还是通过程序编码实现的,它都将自动继承父类的所有便利构造器。

    

    2. 如果子类中定义的构造器与父类中指定构造器的形参列表、外部形参名相同,即可认为子类构造器重写了父类构造器,此时需要在构造器前面用override关键字修饰----override关键字强制Swift编译器执行严格的检查,以保证该构造器确实重写了父类构造器。

    

    3. 只要子类构造器重写了父类的指定构造器,则必须在子类构造器前添加override修饰符,即使子类构造器是一个便利构造器(此时便利构造器前同时出现override convenience两个修饰符)

    

    4. 对于父类的便利构造器来说:如果子类中定义的构造器只是与父类中便利构造器的形参列表、外部形参名相同----虽然看起来很像重写父类构造器,但由于子类永远不可以直接调用父类的便利构造器,因此这其实不算构造器的重写,所以也不用override关键字。

    

    5. 类与可能失败的构造器:对于值类型(枚举、结构体)的可能失败的结构体而言,在该构造器实现体的任意地方都可以通过return nil来触发构造失败。对于类来说,可能失败的构造器必须满足如下两个条件之后才能触发:

    1)该类中的所有实例存储属性都已经悲哀赋初始值(既可由程序显式地指定初始值,也可由系统隐式分配默认的初始值)

    2)所有的构造器调用都已经被执行(即:return nil不能位于self.init(参数)super.init(参数)代码之前)

    

    6. 举个栗子:

    class User

    {

    var name : String

    init?(name : String)

    {

    //必须先对name实例存储属性设置初始值,然后才能触发构造失败

    self.name = ""

    如果传入的name参数为空字符串,构造失败,返回nil

    if name.isEmpty

    {

    return nil

    }

    self.name = name

    }

    }

    

    上面代码中,如果将self.name = ""去掉,将会导致编译错误。如果希望在去掉的情况下不报错,也可以将name声明为可选类型:  var name : String!

    

    7.可能失败的构造器的传播:类、结构体、枚举的构造器可以横向调用该类型中另一个可能失败的构造器,类似地,子类的可能失败的构造器也可以向上调用父类的可能失败的构造器。

    

    8. 可能失败的构造器可以调用同一个类中的普通构造器,反过来,普通构造器不能调用同一个类中可能失败的构造器。但是在结构体中,普通构造器却可以调用同一个结构体中可能失败的构造器。

    

    9. 由于可能失败的构造器会产生传播,因此当可能失败的构造器在构造过程失败之后,这种失败行为会立即阻止原来构造器代码继续向下执行。

    

    10. 举个栗子:

    class Student : User

    {

    var grade : Int!

    init!(name : String, grade : Int)

    {

    //调用父类的可能失败的构造器

    super.init(name : name)

    //如果grade小于1,则使用return nil触发构造失败

    if grade < 1

    {

    return nil

    }

    self.grade = grade

    }

    }

    

    let s1 = Student(name : "", grade : 3)

    print(s1 == nil)

    因为name为空,所以在super.init处返回了nil,因此super.init之后的所有代码都不会被执行。

    

    11. 重写可能失败的构造器:子类可以重写父类的可能失败的构造器,子类既可以用可能失败的构造器,也可以用普通的构造器重写父类的可能失败的构造器----这样可以保证被重写后的构造器不可能失败。

    

    12. 注意:子类的普通构造器可以重写父类的可能失败的构造器,但子类的普通构造器不能向上调用父类的可能失败的构造器。对于类的构造器而言,普通构造器永远不能调用可能失败的构造器,不管是父类的可能失败的构造器还是同一个类中可能失败的构造器。

    

    13. Swift中运行在父类构造器前面添加required关键字,该关键字用于声明所有子类必须包含该required构造器。

    

    14. 父类中声明的required构造器既可以是指定构造器,也可以是便利构造器。

    

    15. required关键字 ******要求所有子类必须包含required构造器,至于子类是编码实现,还是继承得到的,Swift并不关心,至于子类采用指定构造器还是便利构造器,Swift也不关心。

    

    16. 举个栗子:

    class Fruit

    {

    var name : String

    var weight : Double

    //定义required的指定构造器

    required inti(name : String)

    {

    self.name = name 

    self.weight = 0.0

    }

    //定义required的便利构造器

    required convenience init(name : String, weight : Double)

    {

    self.init(name)

    self.weight = weight

    }

    }

    class Apple : Fruit

    {

    var color : String

    //重写父类的required的便利构造器

    required init(name : String, weight : Doublee)

    {

    self.color = "pink"

    super.init(name : name

    }

    init(color : String)

    {

    self.color = color

    super.init(name : "")

    }

    

    //重写父类的required的指定构造器

    //虽然此处属于构造器重写,但无须添加override

    required convenience init(name : String)

    {

    self.init(color : "aaa"

    super.name = name

    }

    }

    

    //该类将会继承得到父类的required构造器

    class Grape : Fruit

    {

    var sugarRate : Double = 0.45

    }

    因为Grape中没有定义任何指定构造器,因此,它将会得到父类的所有指定构造器和便利构造器。

    

    

    17. 析构器:在实例被销毁之前,程序可能需要释放一些物理资源(并非释放内存,内存释放由系统自动完成),比如关闭文件、断开网络链接等等,此时可以借助于析构器来实现。

    

    18. 析构器是一个名为deinit的函数(也无须用func关键字)析构器deinit没有返回值,也没有参数(甚至不能有圆括号)因此不能重载它。

    

    19. 析构器在实例释放之前由系统自动调用,因此不要主动调用析构器子类自动继承父类的析构器,如果子类实现了自己的析构器,子类析构器执行结束时将自动调用父类的析构器。无论如何,子类析构器一定会调用父类析构器。

    

    20. 由于只有等到析构器被调用完成后,该实例才会被被销毁,因此析构器可以访问该实例的所有实例存储属性,或者根据这些属性来关闭资源。

    

    21.举个栗子:

    class Fruit

    {

    var name : String

    var weight : Double

    init(name : String)

    {

    self.name = name

    self.weight = 0.0

    }

    deinit

    {

    print("in Fruit -- this object will be destoryed")

    }

    }

    

    class Apple : Fruit

    {

    var color : String

    init(name : String, weight : Double, color : String)

    {

    self.color = color

    super.init(name : name)

    }

    deinit

    {

    print("in Apple -- this object will be destoryed")

    }

    }

    

    注意:应该使用swiftc命令编译该程序,然后再运行,才可以看到预想的结果,再Palyground中运行该程序将看不到该效果。因为:Playground只是一个临时性的练习场所。

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

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




原创粉丝点击