// 析构器 只适用与 类类型, 当一个类的实例被释放之前, 析构器会被立即调用, 析构器用关键字 deinit 来标示, 类似于构造器要用 init 来标示

// 析构过程原理

// Swift 会自动释放不再需要的实例以释放资源, 如 自动引入计数 章节中所描述, Swift 通过自动引用计数 (ARC) 处理实例的不存管理. 通常当你的实例被释放是不需要 手动去清理, 但是, 当使用自己的资源时, 你可能需要进行一些额外的清理, 例如, 如果创建了一个自定义的类来打开文件, 并写入一些数据, 你可能需要在类实例被释放之前手动去关闭该文件

// 在类的定义中, 每个类最多只能有一个析构器, 而且析构器不带任何参数

// deinit{

// 执行析构过程

// }

// 析构器是在实例释放发生前被自动调用, 你不能主动调用 析构器, 子类继承了父类的析构器, 并且在子类析构器实现的最后, 父类的析构器 会被自动调用, 即使子类没有提供自己的析构器, 父类的析构器也同样会被调用

// 因为直到实例的 析构器被调用后, 实例才会被释放, 所以析构器可以访问实例的所有属性, 并且可以根据那些属性可以修改它的行为 (比如查找一个需要关闭的文件)

// 析构器实践

// 这是一个析构器实践的例子, 这里定义了两种新类型, 分别是 Bank 和 Player

// Bank 类管理一种虚拟硬币, 确保流通的硬币数量永远不可能超过 10000, 在游戏中有且只能有一个 Bank 存在, 因此 Bank 用类来实现, 并使用类型属性 和 类型方法 来 存储和管理其当前状态

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

}

}

// Bank 使用 coinsInBank 属性来跟踪它当前拥有的硬币数量, Bank 还提供了两个方法, distribute(coins:) 和 receive(coins:) , 分别用来处理硬币的 分发 和 收集

// distribute(coins:) 方法在 Bank 对象分发硬币之前检查是否有足够的硬币, 如果硬币不足, Bank 对象会返回一个比请求时小的数字, (如果不够, 有多少发多少, 没有就发 0), 此方法返回一个整型值, 表示提供硬币的实际数量, receive(coins:) 方法只是将 Bank 实例接收到的硬币数目加回硬币存储中

// Player 类描述了游戏中的一个玩家, 每一个玩家在任意时间都有一定数量的硬币存储在他们的其阿宝中, 这通过玩家的 coinsInPurse 属性来表示

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 实例在初始化的过程中, 都从 Bank 对象获取指定数量的硬币, 如果没有足够的硬币可用, Player 实例可能会收到比指定数量少的 硬币

// Player 类定义了一个 win(coins:) 方法, 该方法从 Bank 对象获取一定数量的硬币, 并把它们添加到玩家的钱包,

// Player 类还实现了一个析构器, 这个析构器在 Player 实例释放前被调用, 在这里, 析构器的作用只是将玩家的所有硬币都返还给 Bank 对象

var playerOne: Player? = Player(coins: 100)

print("A new player has joined the game with \(playerOne!.coinsInPurse) coins")

print("There are now \(Bank.coinsInBank) coins left in the bank")

// 创建一个Player实例的时候,会向Bank对象请求 100 个硬币,如果有足够的硬币可用的话。这个Player实例存储在一个名为playerOne的可选类型的变量中。这里使用了一个可选类型的变量,因为玩家可以随时离开游戏,设置为可选使你可以追踪玩家当前是否在游戏中。

// 因为playerOne是可选的,所以访问其coinsInPurse属性来打印钱包中的硬币数量时,使用感叹号(!)来解包:

playerOne!.win(coins: 2_000)

print("PlayerOne won 2000 coins & now has \(playerOne!.coinsInPurse) coins")

// 输出 "PlayerOne won 2000 coins & now has 2100 coins"

print("The bank now only has \(Bank.coinsInBank) coins left")

// 输出 "The bank now only has 7900 coins left"

// 这里,玩家已经赢得了 2,000 枚硬币,所以玩家的钱包中现在有 2,100 枚硬币,而Bank对象只剩余 7,900 枚硬币。

playerOne = nil

print("PlayerOne has left the game")

// 打印 "PlayerOne has left the game"

print("The bank now has \(Bank.coinsInBank) coins")

// 打印 "The bank now has 10000 coins"

// 玩家现在已经离开了游戏。这通过将可选类型的playerOne变量设置为nil来表示,意味着“没有Player实例”。当这一切发生时,playerOne变量对Player实例的引用被破坏了。没有其它属性或者变量引用Player实例,因此该实例会被释放,以便回收内存。在这之前,该实例的析构器被自动调用,玩家的硬币被返还给银行。

swift 学习- 17 -- 析构器的更多相关文章

  1. Swift 析构器deinit

    析构器只适用于类类型,当一个类的实例被释放之前,析构器会被立即调用.析构器用关键字deinit来标识,类似于构造器用init来标识. 原理: Swift会自动释放不再需要的实例以释放资源.Swift通 ...

  2. swift学习笔记之-析构过程

    //析构过程deist import UIKit /*析构过程(Deinitialization):析构器只适用于类类型,当一个类的实例被释放之前,析构器会被立即调用.析构器用关键字deinit来标示 ...

  3. Swift构造器(Initializer)与析构器(Deinitializer)

    为了初始化结构体和类等类型的实例属性. 默认构造器 struct Fahrenheit { var temperature: Doubleinit(){ temperature = 32.0 } } ...

  4. Swift中子类必须包含的构造器和析构器

    import Foundation /* Swift中子类必须包含的构造器 1.Swift允许在父类构造器前添加required关键字, 用于声明所有子类必须包含该required构造器 (如果没有声 ...

  5. objective-C学习笔记(五)函数成员:初始化器和析构器

    初始化器:init 对象初始化器: -(id)init 可以重载多个. 类型初始化器: +(id)initialize只能有一个. 对象初始化器: 初始化对象实例时,init通常和alloc(手动内存 ...

  6. swift学习笔记4——扩展、协议

    之前学习swift时的个人笔记,根据github:the-swift-programming-language-in-chinese学习.总结,将重要的内容提取,加以理解后整理为学习笔记,方便以后查询 ...

  7. swift学习笔记3——类、结构体、枚举

    之前学习swift时的个人笔记,根据github:the-swift-programming-language-in-chinese学习.总结,将重要的内容提取,加以理解后整理为学习笔记,方便以后查询 ...

  8. Swift中类的初始化器与继承

    初始化是类,结构体和枚举类型实例化的准备阶段.这个阶段设置这个实例存储的属性的初始化数值和做一些使用实例之前的准备以及必须要做的其他一些设置工作. 通过定义构造器(initializers)实现这个实 ...

  9. 【Swift学习】Swift编程之旅---构造方法(十八)

    初始化是为了使用某个类.结构体或枚举类型的实例而进行的准备过程.这个过程包括为每个存储的属性设置一个初始值,然后执行新实例所需的任何其他设置或初始化.   初始化是通过定义构造器(Initialize ...

随机推荐

  1. Immunity Debugger学习

    1.Immunity Debugger简介 Immunity Debugger软件专门用于加速漏洞利用程序的开发,辅助漏洞挖掘以及恶意软件分析.它具备一个完整的图形用户界面,同时还配备了迄今为止最为强 ...

  2. oracle 窗口函数over

    select *,sum(字段) over()from table :--相加所有行这个字段的和 select max(字段1),over(partition by  字段2,字段3) from ta ...

  3. 简单重写容器vector

    #pragma once #include <iostream> using namespace std; template<class T> class CMyVector ...

  4. JQ中的 offsetTop 和 offset().top 的区别

    话不多说先上图: offset()的top是指元素与document的上边的距离,而不是浏览器当前窗体的上边缘,如图 document高度超过window,浏览器出现滚动条,滚动滚动条,提交按钮的of ...

  5. B - Tree Rotations HYSBZ - 2212 (线段树合并)

    题目链接:https://cn.vjudge.net/contest/287725#problem/B 题目大意:现在有一棵二叉树,所有非叶子节点都有两个孩子.在每个叶子节点上有一个权值(有n个叶子节 ...

  6. Struts2-052 漏洞复现

    s2-052漏洞复现 参考链接: http://www.freebuf.com/vuls/147017.html http://www.freebuf.com/vuls/146718.html 漏洞描 ...

  7. Navicat for Mysql连接mysql数据库时出现 2003-Can't connect to MySql server on 'localhost'(10061)

    一.环境:linux服务器下 二.问题:在windows7下使用Navicat for Mysql连接mysql数据库时出现 2003-Can't connect to MySql server on ...

  8. 编程基础 - 0x00008 的0x代表什么?

    总结: 二进制:0dXXXX 八进制:0XXXX 十六进制:0xXXXX ------------------------------- 1- 十六进制 以“0x”开始的数据表示16进制,计算机中每位 ...

  9. 手写代码注意点--java.util.Stack相关

    1-Stack的基本函数为: 注意: 取栈顶的函数为peek(),不是top()... 测试stack是否为空的函数为empty(),不是isEmpty()...

  10. TreeGrid 控件集 :delphi 学习群 ---- 166637277 (Delphi学习交流与分享)

    delphi 学习群: 166637277  (Delphi学习交流与分享). 群主QQ: 1936431438 TreeGrid 控件集 收集: 1.https://www.lmd.de/produ ...