Deinitialization

当类的实例对象即将要被释放时,会立即调用deinitializer,通过deinit关键字来定义deinitializer,和initializer一样,它也只存在于类类型上。

当实例对象不再有用时,Swift会自动释放该对象。Swift通过自动引用计数(ARC)来管理实例内存。通常情况下,对象被释放时,你并不需要做特别的清理,但是,如果你操作了你自己的资源,可能需要做一些额外的清理工作。比如,你在某个类中打开了一个文件,并往里写入了数据,那么你需要在这个类的实例对象释放前关闭文件。

一个类最多只能有一个deinitializer,并且它不接受任何参数,定义方式也是无参数形式:

deinit {
// perform the deinitialization
}

deinitializer是自动在合适的时刻被调用的,你不能手动调用它。

超类的deinitializer会自动被子类继承,并且超类的deinitializer会自动在子类的deinitializer实现完成之后被调用。当然,如果子类并没有提供deinitializer的实现,超类的deinitializer依然会被自动调用。因为实例对象是在deinitializer被调用完成之后才会被释放,因此deinitializer可以访问实例对象的所有属性,并且基于这些属性实现一些操作(比如查询需要被关闭的文件名字)。

struct Bank {
static var coinsInBank = 10_000
static func vendCoins(var numberOfCoinsToVend: Int) -> Int {
numberOfCoinsToVend = min(numberOfCoinsToVend, coinsInBank)
coinsInBank -= numberOfCoinsToVend
return numberOfCoinsToVend
}
static func receiveCoins(coins: Int) {
coinsInBank += coins
}
}

这里定义了一个结构体来模拟一个简单的游戏虚拟银行,它负责整个游戏里的货币存储和借贷,它声明了一个类型属性coinsInBank来跟踪银行里面的现金数。这里vendCoins方法定义了一个变量型参数,这样它就不用在方法体内部再声明一个变量然后赋值,而是直接操作这个变量型参数就可以了。

class Player {
var coinsInPurse: Int
init(coins: Int) {
coinsInPurse = Bank.vendCoins(coins)
}
func winCoins(coins: Int) {
coinsInPurse += Bank.vendCoins(coins)
}
deinit {
Bank.receiveCoins(coinsInPurse)
}
}

Player模拟游戏中的玩家,它声明一个存储属性coinsInPurse来标识这个实例对象当前拥有的金币数。在init和winCoins两个方法中,虽然接受了一个coins参数,但是并不是直接将其赋值给存储属性,而是取决于Bank能够借贷出来的金币数。这里定义了一个deinitializer,在当前实例对象被释放之前将所拥有的金币归还给银行。

var playerOne: Player? = Player(coins: )
println("A new player has joined the game with \(playerOne!.coinsInPurse) coins")
// prints "A new player has joined the game with 100 coins"
println("There are now \(Bank.coinsInBank) coins left in the bank")
// prints "There are now 9900 coins left in the bank”

这里定义了一个可选Player类型变量playerOne,之所以定义为可选类型,是因为该玩家可以随时离开游戏,即该对象随时可能被释放。这里要访问它的存储属性时,用了隐式展开可选项符号(!),同样,在调用它的实例方法时也要这样:

playerOne!.winCoins(2_000)
println("PlayerOne won 2000 coins & now has \(playerOne!.coinsInPurse) coins")
// prints "PlayerOne won 2000 coins & now has 2100 coins"
println("The bank now only has \(Bank.coinsInBank) coins left")
// prints "The bank now only has 7900 coins left”

当playerOne被释放时,在此之前会先执行它的deinitializer进行相关的清理工作,即将钱还给银行:

playerOne = nil
println("PlayerOne has left the game")
// prints "PlayerOne has left the game"
println("The bank now has \(Bank.coinsInBank) coins")
// prints "The bank now has 10000 coins”

Swift学习笔记十四的更多相关文章

  1. Swift学习笔记十四:构造(Initialization)

         类和结构体在实例创建时,必须为全部存储型属性设置合适的初始值. 存储型属性的值不能处于一个未知的状态.     你能够在构造器中为存储型属性赋初值,也能够在定义属性时为其设置默认值.下面章节 ...

  2. python3.4学习笔记(十四) 网络爬虫实例代码,抓取新浪爱彩双色球开奖数据实例

    python3.4学习笔记(十四) 网络爬虫实例代码,抓取新浪爱彩双色球开奖数据实例 新浪爱彩双色球开奖数据URL:http://zst.aicai.com/ssq/openInfo/ 最终输出结果格 ...

  3. (C/C++学习笔记) 十四. 动态分配

    十四. 动态分配 ● C语言实现动态数组 C语言实现动态数组,克服静态数组大小固定的缺陷 C语言中,数组长度必须在创建数组时指定,并且只能是一个常数,不能是变量.一旦定义了一个数组,系统将为它分配一个 ...

  4. Swift学习笔记十六:协议

    Protocol(协议)用于统一方法和属性的名称,而不实现不论什么功能. 协议可以被类.枚举.结构体实现.满足协议要求的类,枚举,结构体被称为协议的遵循者. 遵循者须要提供协议指定的成员,如属性,方法 ...

  5. Swift 学习笔记(四)

    116.使用可选链式调用代替强制展开 通过在想调用的属性.方法.或下标的可选值(optional value)后面放一个问号(?),可以定义一个可选链.这一点很像在可选值后面放一个叹号(!)来强制展开 ...

  6. 【swift学习笔记】四.swift使用Alamofire和swiftyJson

    Alamofire是AFNetworking的swift版本,功能灰常强大. github:https://github.com/Alamofire/Alamofire SwiftyJSON是操作js ...

  7. SharpGL学习笔记(十四) 材质:十二个材质球

    材质颜色 OpenGL用材料对光的红.绿.蓝三原色的反射率来近似定义材料的颜色.象光源一样,材料颜色也分成环境.漫反射和镜面反射成分,它们决定了材料对环境光.漫反射光和镜面反射光的反射程度.在进行光照 ...

  8. Swift学习笔记十五

    自动引用计数(Automatic Reference Counting) 和OC一样,Swift用自动引用计数机制来跟踪和管理你应用程序的内存,大多数情况下,你不需要考虑自己管理内存,Swift会自动 ...

  9. Swift学习笔记十二

    方法 方法就是和某种特定类型相关联的函数.类.结构体.枚举都可以定义实例方法和类型方法.类型方法和OC中的类方法类似. 结构体和枚举也可以定义方法是Swift与C/OC之间很大的一个区别,在OC中,只 ...

随机推荐

  1. A+B for Matrices 及 C++ transform的用法

    题目大意:给定两个矩阵,矩阵的最大大小是M*N(小于等于10),矩阵元素的值的绝对值小于等于100,求矩阵相加后全0的行以及列数. #include<iostream> using nam ...

  2. jquery自动将form表单封装成json的具体实现

    前端页面:<span style="font-size:14px;"> <form action="" method="post&q ...

  3. 提问:"~"运算符

    本人有一段代码关于"~"运算符 public class m{ public static void main(String[] args){ int x=~5; System.o ...

  4. gcc都做了什么优化

    直接上程序: setjmp和longjmp是处理函数嵌套调用的,goto语句不能跨越函数,所以不选择goto. #include <setjmp.h> int setjmp(jmp_buf ...

  5. Apriori算法例子

    1 Apriori介绍 Apriori算法使用频繁项集的先验知识,使用一种称作逐层搜索的迭代方法,k项集用于探索(k+1)项集.首先,通过扫描事务(交易)记录,找出所有的频繁1项集,该集合记做L1,然 ...

  6. 30+简约时尚的Macbook贴花

    当Macbooks Pro电脑在他们的设计之下仍然漂亮.独一无二时,我想说,他们已经成为相当的主流了.有时候如果你回忆过去的很美好的日子,当人们偷偷欣赏你的技术装备 的时候,大概是为你的外表增加亮点的 ...

  7. [POJ] #1005# I Think I Need a Houseboat : 浮点数运算

    一. 题目 I Think I Need a Houseboat Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 97512 ...

  8. 【MySQL】源码编译安装和配置MySql 5.5.32(单实例)

    [需求描述] 在CentOS环境中,通过编译源码的方式,安装并且配置“单实例”的MySQL5.5.32数据库. MySQL的安装目录为:/application/mysql-5.5.32 MySQL数 ...

  9. C++11之使用或禁用对象的默认函数

    [C++11之使用或禁用对象的默认函数] C++11 允许显式地表明采用或拒用编译器提供的内置函数.例如要求类型带有默认构造函数,可以用以下的语法: 另一方面,也可以禁止编译器自动产生某些函数.如下面 ...

  10. C# winform只有一个进程

    在做winform程序的时候,有时候需要客户只能起一个进程,不能起多个进程,用如下代码可以实现. internal static class Program { private static Mute ...