// 析构器 只适用与 类类型, 当一个类的实例被释放之前, 析构器会被立即调用, 析构器用关键字 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. Python 生成requirement 使用requirements.txt安装类库

    快速生成requirement.txt的安装文件 (CenterDesigner) xinghe@xinghe:~/PycharmProjects/CenterDesigner$ pip freeze ...

  2. 四十、Linux 线程——互斥锁和读写锁

    40.1 互斥锁 40.1.1 介绍 互斥锁(mutex)是一种简单的加锁的方法来控制对共享资源的访问. 在同一时刻只能有一个线程掌握某个互斥锁,拥有上锁状态的线程能够对共享资源进行访问. 若其他线程 ...

  3. 三十六、Linux 线程——线程基本概念及线程的创建和终止

    36.1 线程介绍 36.1.1 线程的基本概念 进程是资源管理的最小单位,线程是程序执行的最小单位 每个进程都有自己的数据段.代码段和堆栈段. 线程通常叫做轻型的进程,它包含独立的栈和 CPU 寄存 ...

  4. string赋值和操作

    string赋值 string s1; //默认构造函数,s1为空串 string s1(s2); //将s2初始化为s1的一个副本 string s3("value"); //将 ...

  5. 图像分类中max-pooling和average-pooling之间的异同

    池化操作时在卷积神经网络中经常采用过的一个基本操作,一般在卷积层后面都会接一个池化操作,但是近些年比较主流的ImageNet上的分类算法模型都是使用的max-pooling,很少使用average-p ...

  6. ue4 编辑器记录

    Matinee 编辑器 菜单:Add New Empty Group->选择要变动的Actor->菜单:Add Actor->菜单:Add Key->变更Actor属性-> ...

  7. python前后端加密方式

    后端加密方法: python后端加密方式: # 双重工加密 #bytes((7788).encode('utf-8')):为后端加密二把手,多加的锁,该参数可为空,必须加bytes才能实现 md5pa ...

  8. python之import模块及包的调用

    模块概念 在Python中,一个.py文件就称之为一个模块(Module).使用模块组织代码,最大的好处是大大提高了代码的可维护性 模块一共三种:python标准库.第三方模块.应用程序自定义模块. ...

  9. undefined symbol

    参考链接:  https://blog.csdn.net/shatterheart/article/details/52440149

  10. 数组去重的4种方法(Which one is the fastest???嘻嘻嘻....)

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...