继续学习Swift文档,从上一章节:初始化,咱们学习了Swift初始化相关的内容,如类、结构体和枚举初始化方法的定义和使用、 convenience 关键词定义便捷初始化方法、初始化失败语法 init? 和强制解包 init!、 required关键词修饰init方法、用闭包和函数设置属性默认值等这些内容。如今,咱们学习Swift的析构函数相关的内容。因为篇幅较长,这里分篇来记录,接下来,Fighting!html
题外话:Deinitialization这个翻译过来是“反初始化”,感受不是很对,特地去搜索一下相关内容,最后以为“析构函数”会更适合一点,因此这里就用这个翻译结果为准吧。若是有误,欢迎指正哈^.^!swift
若是你已经掌握了这个,跳转下一章节:可选连接bash
在取消释放类实例以前,将调用析构函数。 您使用deinit关键字编写析构函数,相似于使用init关键字编写初始化方法的方式。 析构函数仅在类类型上可用。闭包
当再也不须要实例时,Swift会自动释放其实例,以释放资源。 Swift经过自动引用计数(ARC)处理实例的内存管理,如自动引用计数中所述。 一般,在释放实例后,您无需执行手动清理。 可是,当您使用本身的资源时,可能须要本身执行一些额外的清理。 例如,若是建立一个自定义类来打开文件并向其中写入一些数据,则可能须要在释放该类实例以前关闭该文件。ide
每一个类定义最多能够有一个析构函数。 析构函数不接受任何参数,而且写成无括号:函数
deinit {
// perform the deinitialization
}
复制代码
在实例解除分配发生以前,会自动调用析构函数。 您不容许本身调用析构函数。 父类析构函数由其子类继承,而且父类析构函数在子类析构函数实现的末尾自动调用。 即便子类没有提供本身的析构函数,也老是会调用父类析构函数。post
因为实例在调用其取消初始化以后才被释放,所以析构函数能够访问其被调用实例的全部属性,并能够基于这些属性修改其行为(例如查找须要关闭的文件名) )。学习
这是一个实施析构函数的示例。 本示例为一个简单的游戏定义了两种新类型,即Bank和Player。 银行类管理一种虚构货币,流通中的硬币永远不能超过10,000个。 游戏中只能有一个Bank,所以Bank被实现为具备类型属性和存储和管理其当前状态的方法的类:ui
class Bank {
static var coinsInBank = 10_000
static func distribute(coins numberOfCoinsRequested: Int) -> Int {
let numberOfCoinsToVend = min(numberOfCoinsRequested, coinsInBank)
coinsInBank -= numberOfCoinsToVend
return numberOfCoinsToVend
}
static func receive(coins: Int) {
coinsInBank += coins
}
}
复制代码
银行使用coinsInBank属性跟踪当前持有的硬币数量。 它还提供了两种方法(distribute(coins:) 和receive(coins:))来处理硬币的分发和收集。spa
distribute(coins:) 方法在分发以前检查银行中是否有足够的硬币。 若是没有足够的硬币,则Bank返回的数字小于所请求的数字(若是银行中没有剩余硬币,则返回零)。它返回一个整数值以指示所提供的硬币的实际数量。
receive(coins:)方法只是将接收到的硬币数量加回到银行的硬币商店中。Player类描述游戏中的玩家。
每一个玩家随时均可以在钱包中存放必定数量的硬币。 这由玩家的coinInPurse属性表示:
class Player {
var coinsInPurse: Int
init(coins: Int) {
coinsInPurse = Bank.distribute(coins: coins)
}
func win(coins: Int) {
coinsInPurse += Bank.distribute(coins: coins)
}
deinit {
Bank.receive(coins: coinsInPurse)
}
}
复制代码
每一个Player实例在初始化期间都会从银行指定的硬币开始数量进行初始化,尽管若是没有足够的硬币,则Player实例可能会收到少于该数量的硬币。
Player类定义一个win(coins :)方法,该方法从银行中检索必定数量的硬币并将其添加到玩家的钱包中。 Player类还实现了一个析构函数,该初始化器在Player实例被释放以前被调用。 在这里,析构函数只需将玩家的全部硬币返回银行:
var playerOne: Player? = Player(coins: 100)
print("A new player has joined the game with \(playerOne!.coinsInPurse) coins")
// Prints "A new player has joined the game with 100 coins"
print("There are now \(Bank.coinsInBank) coins left in the bank")
// Prints "There are now 9900 coins left in the bank"
复制代码
建立一个新的Player实例,并请求100个硬币(若是有)。 此Player实例存储在一个名为playerOne的可选Player变量中。 这里使用一个可选变量,由于玩家能够随时离开游戏。 可选功能可以让您跟踪游戏中当前是否有玩家。
由于playerOne是可选的,因此当访问其instancesInPurse属性以打印其默认代币数量,而且每当调用其win(coins :)方法时,它都带有一个感叹号(!)。
playerOne!.win(coins: 2_000)
print("PlayerOne won 2000 coins & now has \(playerOne!.coinsInPurse) coins")
// Prints "PlayerOne won 2000 coins & now has 2100 coins"
print("The bank now only has \(Bank.coinsInBank) coins left")
// Prints "The bank now only has 7900 coins left"
复制代码
在这里,玩家赢得了2,000个硬币。 如今,玩家的钱包包含2100个硬币,而银行只剩下7900个硬币。
playerOne = nil
print("PlayerOne has left the game")
// Prints "PlayerOne has left the game"
print("The bank now has \(Bank.coinsInBank) coins")
// Prints "The bank now has 10000 coins"
复制代码
玩家如今已经离开了游戏。 这是经过将可选的playerOne变量设置为nil来表示的,表示“无Player实例”。 发生这种状况时,playerOne变量对Player实例的引用已损坏。 没有其余属性或变量仍在引用Player实例,所以将其释放以释放其内存。 在此以前,它的析构函数会自动被调用,而且其硬币会退还至银行。