Swift学习笔记十四

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: 100)
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”
时间: 2024-10-24 06:24:55

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

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

类和结构体在实例创建时,必须为所有存储型属性设置合适的初始值.存储型属性的值不能处于一个未知的状态. 你可以在构造器中为存储型属性赋初值,也可以在定义属性时为其设置默认值.以下章节将详细介绍这两种方法. 注意: 当你为存储型属性设置默认值或者在构造器中为其赋值时,它们的值是被直接设置的,不会触发任何属性观测器(property observers). 一.基本语法 class Human{ var name :String init(){ name = "human" } init(n

Swift学习笔记十二:下标脚本(subscript)

下标脚本就是对一个东西通过索引,快速取值的一种语法,例如数组的a[0].这就是一个下标脚本.通过索引0来快速取值.在Swift中,我们可以对类(Class).结构体(structure)和枚举(enumeration)中自己定义下标脚本的语法 一.常规定义 class Student{ var scores:Int[] = Array(count:5,repeatedValue:0) subscript(index:Int) -> Int{ get{ return scores[index];

Swift学习笔记十:属性

1.存储属性       1. 作为特定类或结构实例的一部分,存储属性存储着常量或者变量的值.存储属性可分为变量存储属性(关键字var描述)和常量存储属性(关键字let描述). struct student{ let name = "" var score = 0 } let a = student(name:"小笨狼",score:96)           注意:                ① 定义储存属性时,需要为每一个属性定义一个默认值.在初始化的时候,

Swift 学习笔记十五:扩展

扩展就是向一个已有的类.结构体或枚举类型添加新功能(functionality).扩展和 Objective-C 中的分类(categories)类似.(不过与Objective-C不同的是,Swift 的扩展没有名字.) Swift 中的扩展可以: 1.添加计算型属性和计算静态属性 2.定义实例方法和类型方法 3.提供新的构造器 4.定义下标 5.定义和使用新的嵌套类型 6.使一个已有类型符合某个协议 一.扩展属性,构造器,方法 class Human{ var name:String? va

laravel3学习笔记(十四)

原作者博客:ieqi.net ==================================================================================================== 运行时配置 在 Laravel3 中很多地方我们都可以看到“约定大于配置”的影子,我本人也很喜欢这种工程哲学尤其是在框架领域,当然这并不能代替所有的配置.我们知道 Laravel3 中,主要配置都写在 application/config 文件夹下,在应用逻辑中,往往

Swift学习笔记十六:协议

Protocol(协议)用于统一方法和属性的名称,而不实现不论什么功能. 协议可以被类.枚举.结构体实现.满足协议要求的类,枚举,结构体被称为协议的遵循者. 遵循者须要提供协议指定的成员,如属性,方法,操作符,下标等. 一.协议的基本的语法 咱们还是先上代码吧 protocol Human { var name:String{ get set } var isMan:Bool{set get} class var isUsable:Bool { set get } //类成员.表示这个类是否可用

Swift 学习笔记(四)

116.使用可选链式调用代替强制展开 通过在想调用的属性.方法.或下标的可选值(optional value)后面放一个问号(?),可以定义一个可选链.这一点很像在可选值后面放一个叹号(!)来强制展开它的值.它们的主要区别在于当可选值为空时可选链式调用只会调用失败,然而强制展开将会触发运行时错误. 为了反映可选链式调用可以在空值(nil)上调用的事实,不论这个调用的属性.方法及下标返回的值是不是可选值,它的返回结果都是一个可选值.你可以利用这个返回值来判断你的可选链式调用是否调用成功,如果调用有

Swift学习之十四:闭包(Closures)

* 闭包(Closures) * 闭包是自包含的功能代码块,可以在代码中使用或者用来作为参数传值. * 在Swift中的闭包与C.OC中的blocks和其它编程语言(如Python)中的lambdas类似. * 闭包可以捕获和存储上下文中定义的的任何常量和变量的引用.这就是所谓的变量和变量的自封闭, * 因此命名为”闭包“("Closures)").Swift还会处理所有捕获的引用的内存管理. * * 全局函数和嵌套函数其实就是特殊的闭包. * 闭包的形式有: * (1)全局函数都是闭

Swift学习笔记十二

方法 方法就是和某种特定类型相关联的函数.类.结构体.枚举都可以定义实例方法和类型方法.类型方法和OC中的类方法类似. 结构体和枚举也可以定义方法是Swift与C/OC之间很大的一个区别,在OC中,只有类才能定义方法. 实例方法 实例方法是从属于某个类实例或结构体实例.枚举实例的方法.他们提供与该实例相关的功能,比如获取更改属性或者提供其他函数功能.实例方法的语法和函数完全相同. 实例方法隐式地可以访问该类型的属性和方法.只能从该类型的实例上调用实例方法.比如: class Counter {