在一个类的实例内存被释放之前,析构方法被立即调用。使用deinit关键字来声明析构方法,类似于构造方法用init来声明。析构方法只适用于类类型。

  析构方法原理
Swift会自动释放不再需要的实例以释放资源。如自动引用计数那一章描述,Swift通过自动引用计数(ARC)处理实例的内存管理。不需要手动的去清理。但是,当使用自己的资源时,你可能需要进行一些额外的清理。例如,如果创建了一个自定义的类来打开一个文件,并写入一些数据,你可能需要在类实例被释放之前关闭该文件。
在类的定义中,每个类最多只能有一个析构方法。反初始化函数不带任何参数,在写法上不带括号:
deinit { // 析构} 

析构方法是在实例释放发生前一步被自动调用。不允许主动调用自己的析构方法。子类继承了父类的析构方法,并且在子类析构方法实现的最后,父类的析构方法被自动调用。即使子类没有提供自己的析构方法,父类的析构方法也总是被调用。
因为直到实例的析构方法被调用时,实例才会被释放,所以析构方法可以访问所有请求实例的属性,并且根据那些属性可以修改它的行为(比如查找一个需要被关闭的文件的名称)。
析构方法操作
这里是一个析构方法操作的例子。这个例子是一个简单的游戏,定义了两种新类型,Bank和Player。Bank结构体管理一个虚拟货币的流通,在这个流通中Bank永远不可能拥有超过10,000的硬币。在这个游戏中有且只能有一个Bank存在,因此Bank由带有静态属性和静态方法的结构体实现,从而存储和管理其当前的状态。
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 } } 

Bank根据它的coinsInBank属性来跟踪当前它拥有的硬币数量。银行还提供两个方法—vendCoins和receiveCoins,用来处理硬币的分发和收集。
vendCoins方法在bank分发硬币之前检查是否有足够的硬币。如果没有足够多的硬币,bank返回一个比请求时小的数字(如果没有硬币留在bank中就返回0)。vendCoins方法声明numberOfCoinsToVend为一个变量参数,这样就可以在方法体的内部修改数字,而不需要定义一个新的变量。vendCoins方法返回一个整型值,表明了提供的硬币的实际数目。
receiveCoins方法只是将bank的硬币存储和接收到的硬币数目相加,再保存回bank。
Player类描述了游戏中的一个玩家。每一个player在任何时刻都有一定数量的硬币存储在他们的钱包中。这通过player的coinsInPurse属性来体现:
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实例都由一个指定数目硬币组成的启动额度初始化,这些硬币在bank初始化的过程中得到。如果没有足够的硬币可用,Player实例可能收到比指定数目少的硬币。
Player类定义了一个winCoins方法,该方法从bank获取一定数量的硬币,并把它们添加到player的钱包。Player类还实现了一个反初始化函数,这个反初始化函数在Player实例释放前一步被调用。这里反初始化函数只是将player的所有硬币都返回给bank:
var playerOne: Player? = Player(coins: 100)
println("A new player has joined the game with \ (playerOne!.coinsInPurse) coins")
// 输出 "A new player has joined the game with 100     coins"
println("There are now \(Bank.coinsInBank) coins left    in the bank")
// 输出 "There are now 9900 coins left in the bank" 

一个新的Player实例随着一个100个硬币(如果有)的请求而被创建。这个Player实例存储在一个名为playerOne的可选Player变量中。这里使用一个可选变量,是因为players可以随时离开游戏。设置为可选使得你可以跟踪当前是否有player在游戏中。
因为playerOne是可选的,所以由一个感叹号(!)来修饰,每当其winCoins方法被调用时,coinsInPurse属性被访问并打印出它的默认硬币数目。
playerOne!.winCoins(2_000)
println("PlayerOne won 2000 coins & now has \    (playerOne!.coinsInPurse) coins")
// 输出 "PlayerOne won 2000 coins & now has 2100 coins"
println("The bank now only has \(Bank.coinsInBank) coins left")
// 输出 "The bank now only has 7900 coins left" 

这里,player已经赢得了2,000硬币。player的钱包现在有2,100硬币,bank只剩余7,900硬币。
playerOne = nil
println("PlayerOne has left the game")
// 输出 "PlayerOne has left the game"
println("The bank now has \(Bank.coinsInBank) coins")
// 输出 "The bank now has 10000 coins"  

player现在已经离开了游戏。这表明是要将可选的playerOne变量设置为nil,意思是"没有Player实例"。当这种情况发生的时候,playerOne变量对Player实例的引用被破坏了。没有其它属性或者变量引用Player实例,因此为了清空它占用的内存从而释放它。在这发生前一步,其析构方法被自动调用,其硬币被返回到bank。

【Swift学习】Swift编程之旅---析构方法(十九)相关推荐

  1. Python编程基础:第四十九节 鸭子类型Duck Typing

    第四十九节 鸭子类型Duck Typing 前言 实践 前言 本节我们一起学习一个非常有趣的知识点:鸭子类型.有这么一句话:If it walks like a duck, and it quacks ...

  2. Python编程基础:第三十九节 面向对象编程Object Oriented Programming

    第三十九节 面向对象编程Object Oriented Programming 前言 实践 前言 到目前为止我们都是函数式编程,也即将每一个功能块写为一个函数.其实还有一种更常用的编程方式被称为面向对 ...

  3. 学习Java编程equals()和hashCode()方法

    equals()和hashCode()区别? equals():反映的是对象或变量具体的值,即两个对象里面包含的值--可能是对象的引用,也可能是值类型的值. hashCode():计算出对象实例的哈希 ...

  4. Swift学习——Swift解释特定的基础(七)

    Implicitly Unwrapped Optionals    隐式解析选项 如上所述.可选意味着常数或变量"没有值".通过可选if声明来推断是否存在值,假设有值析值. 有时候 ...

  5. Java架构师之旅(二十九 附录《MyBatis3 用户指南》中文版)

    夜光序言: 岁月波光粼粼,赋予爱与生命,唯有生活不能被他人代替,只会有寂寞相随~~ 正文: MyBatis 3 2010.08.01  翻译的一个版本,虽难比较老了,但是有一些基础还是值得学习,毕竟是 ...

  6. 深度学习核心技术精讲100篇(十九)--GBDT(梯度提升树) 和 Resnet (残差网络)的原理

    残差 残差在数理统计中是指实际观察值与估计值(拟合值)之间的差.在集成学习中可以通过基模型拟合残差,使得集成的模型变得更精确:在深度学习中也有人利用layer去拟合残差将深度神经网络的性能提高变强.这 ...

  7. Android探索之旅(第二十九篇)手把手教你如何简单创建快应用

    一个新鲜的事物出现我们程序猿们必须保持高度且灵敏的嗅觉,所以不妨我们就去大胆的放开去学习一下快应用,了解它的来龙去脉岂不美哉. 本文大多转载自@鸿洋,感谢对于知识的分享 一.环境搭建 1.安装node ...

  8. Python编程基础:第五十九节 守护线程Daemon Threading

    第五十九节 守护线程Daemon Threading 前言 实践 前言 守护线程是在后台运行的线程,对程序的运行并不重要,你的程序在退出前不会等待守护线程的完成,此类线程的特点是,当程序中主线程及所有 ...

  9. 小说里的编程 【连载之二十九】元宇宙里月亮弯弯

    第二十九章 不曾想到的奇迹 这次从火星上回来,勾叫的心情,久久不能平静,因为每次到火星,还是得依赖外星人才行. 结合两次到火星的经验,需要马上再尝试一次,于是勾叫马上去找了牵凫氏. 勾叫和牵凫氏商量, ...

最新文章

  1. centos6.8 安装nginx
  2. 【剑指Offer】16重建二叉树
  3. File类 读取文件
  4. Redis双机热备方案--转
  5. 6月4日云栖精选夜读丨加拿大AI有多强?一年投入60亿,吸引Hinton、Bengio等大神...
  6. boost::graph_as_tree用法的测试程序
  7. 51 NOD 1049 最大子段和 动态规划 模板 板子 DP
  8. Net Core下使用RabbitMQ比较完备两种方案(虽然代码有点惨淡,不过我会完善)
  9. Mysql数据库——数据类型和约束
  10. 玩冒险岛java卸载_如何删除冒险岛安装了,现在不想玩
  11. 8421BCD码的加6修正的原因
  12. 深恶痛绝,编程界的「劣驱良」
  13. 460. LFU缓存
  14. myQNX account试用申请流程(license申请)
  15. 微信网页授权多应用多域名使用 oauth2授权
  16. [学习笔记]Java如何处理EXCEL的读取
  17. Nagios-config
  18. 计算机怎样检查视力,电脑视力表同样测视力 测试方法要正确
  19. 【3dsMax】如何用VSocde写最简单的MaxScript脚本
  20. java jsp eq_javaWeb核心技术第九篇之JSP

热门文章

  1. python读取超大csv
  2. 联想Z5 Pro划时代旗舰发布,屏占比95.06%售价1998元起
  3. 升级的Electric Cloud平台增添了大型机和微服务功能
  4. Linux系统中CPU忙闲的衡量——load和idle
  5. 我的失败与伟大 —— 产品原型的打造
  6. TimesTen更改CacheGroup管理用户ORACLE结束和TT结束password【TimesTen操作和维修基地】...
  7. (匹配)The Accomodation of Students --HDU --2444
  8. JavaScript 学习笔记— —Arguments
  9. Apache配置问题
  10. 日本新年传统习俗介绍(一)