Swift-27-类的初始化与销毁-对象初始化

类的初始化需要注意继承的问题,默认时类只会提供一个空的构造函数方法,这是和结构体不一样的地方

  1. 指定初始化方法,用于给类的所有属性设置初始值;程序代码没有任何修饰关键字,可以有多个;
  2. 便捷初始化方法,只是一种标识,一般会委托给指定初始化方法来实现;用关键字convenience修饰,可以有多个;
  3. 类的必需初始化方法,一个类要求其子类必须提供特定的初始化方法;
  4. 反初始化方法,在类的实例销毁时执行内存清理过程;用deinit定义,一个类只能有一个此方法

因为默认的初始化方法必须给所有属性设置初始值,则便捷初始化方法则不需要。

默认初始化方法

类的默认初始化方法也是int(){},与结构体不同,类没有默认的成员初始化方法。这解释了为什么之前要给类设置默认值:这样可以利用自带的空初始化方法。比如:let fredTheZombie = Zombie(),其中的空圆括号表示这是一个默认初始化方法。

自定义构造函数

父类

class Monster {
    var town: Town?
    var name: String
    
    var victimPool: Int {
        get {
            return town?.population ?? 0
        }
        set(newVictimPool) {
            town?.population = newVictimPool
        }
    }
    
    //自定义的初始化方法, required 表示所有子类都必须实现此构造方法,否则程序会报错
    required init(town: Town?, monsterName: String) {
        self.town = town
        name = monsterName
    }
    
    func terrorizeTown() {
        if town != nil {
            print("\(name) is terrorizing a town!")
        } else {
            print("\(name) hasn't found a town to terrorize yet...")
        }
    }
}

子类

默认情况下子类不会自动继承父类的初始化方法,目的是希望避免子类在不经意间提供了无法为所有属性赋值的初始化方法,但在下列两种场景中子类会继承父类的初始化方法:

  1. 子类没有定义任何自定义的初始化方法;
  2. 如果子类复写了父类所有指定的初始化方法,也会继承父类的所有便捷初始化方法;
class Zombie: Monster {
    class var spookyNoise: String {
        return "Brains..."
    }
    
    var walksWithLimp: Bool
    private(set) var isFallingApart: Bool
    
    //子类特有的初始化方法
    init(limp: Bool, fallingApart: Bool, town: Town?, monsterName: String) {
        walksWithLimp = limp
        isFallingApart = fallingApart
        super.init(town: town, monsterName: monsterName)
    }
    
    //convenience 关键字用来表示快捷初始化方法
    convenience init(limp: Bool, fallingApart: Bool) {
        self.init(limp: limp, fallingApart: fallingApart, town: nil, monsterName: "Fred")
        if walksWithLimp {
            print("This zombie has a bad knee.")
        }
    }

   //复写父类的初始化方法,可以省略overrid关键字
    required init(town: Town?, monsterName: String) {
        walksWithLimp = false
        isFallingApart = false
        super.init(town: town, monsterName: monsterName) //调用父类构造函数
    }
    
    final override func terrorizeTown() {
        if !isFallingApart {
            town?.changePopulation(-10)
        }
    }

}

程序调用

//调用Zombie指定初始化方法:init(limp: Bool, fallingApart: Bool, town: Town?, monsterName: String) 
//The population has changed to 999995 from 1000005.
//Population: 999995; number of stop lights: 4; region: N/A
var fredTheZombie: Zombie? = Zombie(limp: false, fallingApart: false, town: myTown, monsterName: "Fred")
fredTheZombie?.terrorizeTown()
fredTheZombie?.town?.printDescription()

//调用快捷初始化方法:convenience init(limp: Bool, fallingApart: Bool)
//This zombie has a bad knee.
var convenientZombie = Zombie(limp: true, fallingApart: false)

//Victim pool: Optional(999995)
//The population has changed to 500 from 999995.
//Victim pool: Optional(500)
print("Victim pool: \(fredTheZombie?.victimPool)")
fredTheZombie?.victimPool = 500
print("Victim pool: \(fredTheZombie?.victimPool)")

//调用反初始化方法
//Brains...
//Zombie named Fred is no longer with us.
print(Zombie.spookyNoise)
fredTheZombie = nil

初始化函数参数

初始化的函数参数也和普通函数一样,支持内、外名称加类型这种,也支持一些特殊特性,比如下面的_用法,隐藏外部参数名称。

struct WeightRecordInLBS {
    let weight: Double
    
    //用_来指定
    init(_ pounds: Double) {
        weight = pounds
    }
    init(kilograms kilos: Double) {
        weight = kilos * 2.20462
    } 
}

//
let wr = WeightRecordInLBS(185)
上一篇:如何在虚拟专用服务器上配置 Nginx Web 服务器


下一篇:如果项目在上线后才发现Bug怎么办?-感谢每一个认真阅读我文章的人!!!