zoukankan      html  css  js  c++  java
  • Swift -- 8.2 类的构造与析构

    类中的存储属性必须要在构造过程中设置初始值,加上继承的的属性,类的构造过程比较复杂

    析构器 deinit函数

    在实例销毁之前被系统调用,实例不能自己调用

    值类型的构造器可以直接调用一个其他的构造器,但是类的构造器不可以,必须要用convenience来变成便利构造器,然后才能调用其他的构造器

    如果有父类,需要使用super来调用父类的构造器

    class Apple1 {
        
        var name:String!
        var weight:Double
        
        init(name:String, weight:Double){
            self.name = name
            self.weight = weight
        }
        
        init(nn name:String, weight:Double){//构造器重载
            self.name = name
            self.weight = weight
        }
        
        convenience init(n name:String, w weight:Double){//变成便利构造器来调用其他构造器
            self.init(name:name, weight:weight)
            self.name  = name
        }
        
    }
    
    class Pear: Fruit {
        init(weight:Double){
            super.init()//调用父类的构造器
            self.weight = weight
        }
    }
    

      

    两段式构造

     

    swift类的构造需要两个阶段完成

    第一阶段:先为存储属性分配内容,使用本类的构造器初始化由本类定义的存储属性,然后沿着构造器链向上,逐个调用各父类构造器初始化对应父类定义的存储属性

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

     

    为了保证两段式构造顺利完成,swift提供了四种安全检查

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

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

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

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

     

    swift类的构造器规则比较繁琐,因此处理起来比较容易出错,但如果程序显式地为所有实例存储属性指定初始值,定义构造器时就会简单得多,而且可以直接利用系统默认的构造器(hiahiahia   因为这样做的话,只需要把所有的构造器都写在第一行就永远不会出错了hiahiahia

    class A{
        var name : String
        init(name:String){
            self.name = name
        }
    }
    class B: A {
        var age:Int
        init(age:Int){
            self.age = age
            super.init(name: "")
            self.run()
    
        }
        func run(){
            print("run");
        }
    }
    
    var bb = B(age: 22)
    

      

    构造器的继承和重写

     

    构造器的继承规则

    1 如果子类没有提供任何构造器,那么它会继承父类的所有指定构造器和便利构造器

    2 如果子类实现了父类的所有指定构造器(比如说使用方法1或是重写来实现),那么它将继承父类的所有便利构造器

          反而言之,如果子类自己写了构造器,并且没有重写父类的指定构造器,那么它就不能继承父类的构造器

    class F
    {
        var name : String
        var weight : Double
        init(name:String, weight:Double){
            self.name = name
            self.weight = weight
        }
        init(n name:String){
            self.name = name
            self.weight = 0.0
        }
         convenience init(){
            self.init(n:"")
            self.weight = 1.0
        }
    }
    
    class App: F {
        var color : String
        override init(name:String, weight:Double){
            self.color = ""
            super.init(name: name, weight: weight)
        }
        override init(n name:String){
            self.color = ""
            super.init(n: name)
        }
        init(name:String, weight:Double, color:String){
            self.color = color
            super.init(name: name, weight: weight)
        }
        convenience init(name:String, color:String){
            self.init(name:name, weight:0.0, color:color)
        }
    }
    
    class Fuji: App {
        var vitanim : Double = 0.21
    }
    var ff = App()
    ff.weight
    var tt = Fuji(name: "", color: "")
    
    //子类的构造器不能与父类的构造器的形参列表相同,如果相同需要添加override关键字。但是如果父类的构造器是便利构造器就没有事
    class F2 {
        var name : String
        init(){
            self.name = ""
        }
        
        convenience init(name:String){
            self.init()
        }
    }
    
    class F3: F2 {
        var color : String
        init(name:String){//这个构造器父类中也有,不过父类中是便利构造器,所以子类中依然可以使用
            self.color = ""
            super.init()
        }
    }
    

      

    类与可能失败的构造器

     

    可能失败的构造器必须满足的两个条件

    1 该类中所有实例存储属性都已被赋值

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

     

    如果子类调用父类的可能失败的构造器,那么如果父类的构造器return nil,那么子类构造器中之后的代码都不会被执行

    在重写可能失败的构造器的时候,可以重写成可能失败的构造器,也可以重写成普通构造器

    class User {
        var name : String
        init?(name:String){
            self.name = ""
            if name.isEmpty {
                return nil
            }
            self.name = name
        }
    }
    
    class Student: User {
        var grade : Int!
        init!(name:String, grade:Int){
            super.init(name: name)//如果这个构造器失败,那么之后的代码都不会被执行
            if grade < 1{
                return nil
            }
            self.grade = grade
        }
    }
    //所以在类中,可能失败的构造器可以调用普通的构造器,普通的构造器不能调用可能失败的构造器
    
    class C1 {
        var name : String
        init!(name:String){
            self.name = ""
            if name.isEmpty{
                return nil
            }
            self.name = name
        }
    }
    
    class C2: C1 {
        var color : String
        init?(name:String, color:String){
            self.color = ""
            super.init(name: "")
            
        }
        init(color:String){
            self.color = color
            super.init(name: "")//虽然这里没有报错,但是使用实例的时候会出错的
        }
    }
    let ccccc = C2(name: "", color: "")
    

      

    子类必须包含的构造器

    使用required来标记构造器,表示子类构造器必须包含这个构造器

    可以通过重写和继承来得到

    class Fruit5 {
        var name:String
        required init(name:String){
            self.name = name
        }
        
        
    }
    
    class Apple5: Fruit5 {
        var weight : Double
        init(weight:Double){
            self.weight = weight
            super.init(name: "")
        }
    
        required init(name: String) {//不写这个构造器会报错
            self.weight = 0
            super.init(name: name)
        }
    }
    

      

    析构器

    deinit

    在实例被销毁之前调用

    析构器是系统自动调用的,实例不可以自己调用

    子类的析构器执行结束时将自动调用父类的析构器

    class T1 {
        var name : String = "nn"
        deinit{
            print("the T1 is deinit")
        }
    }
    
    class T2: T1 {
        deinit{
            print("the T2 is deinit")
        }
    }
    var ap:T2? = T2()
    ap!.name
    ap = nil
    //the T2 is deinit
    //the T1 is deinit
    

      

  • 相关阅读:
    一起来做chrome扩展《AJAX请求》
    一起来做chrome扩展《基础介绍》
    Javascript,颜色渐变效果的处理
    一起来做webgame,《Javascript蜘蛛纸牌》
    一起来做webgame,《卡片魔兽》(一)基础战斗
    一起来做webgame,《Javascript贪食蛇》
    gitlab
    kubernetes部署多种服务yaml文件
    [kubernetes集群调度]
    [kubernetes集群调度]
  • 原文地址:https://www.cnblogs.com/chebaodaren/p/5623601.html
Copyright © 2011-2022 走看看