Swift编程十六(Deinitialization)

案例代码下载

Deinitialization

一个类的实例被释放之前立即调用deinitializer。使用deinit关键字编写deinitializers ,类似于使用init关键字编写初始化程序的方式。Deinitializers仅适用于类类型。

Deinitialization如何运作

当不再需要实例时,Swift会自动释放实例,以释放资源。Swift通过处理实例通过自动引用计数(ARC)管理内存,如在自动引用计数中描述。通常,在取消分配实例时,无需执行手动清理。但是,当使用自己的资源时,可能需要自己执行一些额外的清理。例如,如果创建自定义类以打开文件并向其写入一些数据,则可能需要在实例销毁之前关闭该文件。

类定义每个类最多可以有一个deinitializer。deinitializer不接受任何参数,并且没有括号写入:

deinit {
    // 执行deinitialization
}

在实例销毁之前,会自动调用deinitialization。不能自己调用deinitializer。超类deinitializers由其子类继承,超类deinitializer在子类deinitializer实现的末尾自动调用。即使子类不提供自己的deinitializer,也始终调用超类deinitializers。

因为实例在调用deinitializer之后才被释放,所以deinitializer可以访问调用它的实例的所有属性,并可以根据这些属性修改其行为(例如查找需要关闭的文件的名称) )。

Deinitializers in Action

这是一个Deinitializers的例子。这个例子定义了两种新类型,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。它还提供两种方法distribute(coins:)以及receive(coins:)处理硬币的分配和收集。

distribute(coins:)方法在分发之前检查银行中是否有足够的硬币。如果没有足够的硬币,则Bank返回的数字小于请求的数字(如果银行中没有剩余硬币,则返回零)。它返回一个整数值,表示提供的实际硬币数。

receive(coins:)方法简单地将收到的硬币数量添加回银行的硬币商店。

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在初始化期间,每个实例初始化具有来自银行的指定数量的硬币的起始许可,但是Player如果没有足够的硬币可用,则实例可以接收少于该数量的实例。

Player类定义了一个win(coins:)方法,它从银行获取一定数量硬币,并将它们添加到玩家的钱包。Player类还实现了deinitializer,这在Player实例被释放前调用。在这里,deinitializer只是将所有玩家的硬币归还给银行:

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创建一个新实例,如果可用则请求100个硬币。此Player实例存储在名为playerOne的Player可选变量中。这里使用可选变量,因为玩家可以随时离开游戏。可选项可跟踪游戏中当前是否有玩家。

因为playerOne它是可选的,当访问其coinsInPurse属性以打印其默认硬币数时,调用win(coins:)方法时,都会被感叹号(!)限定:

playerOne!.win(coins: 2_000)
print("PlayerOne won 2000 coins & now has \(playerOne!.coinsInPurse) coins")
print("The bank now only has \(Bank.coinsInBank) coins left")

在这里,玩家赢得了2,000个硬币。玩家的钱包现在包含2,100个硬币,银行只剩下7,900个硬币。

playerOne = nil
print("PlayerOne has left the game")
print("The bank now has \(Bank.coinsInBank) coins")

玩家现在已离开游戏。通过将可选playerOne变量设置为nil表示“无Player实例” 来指示。在发生这种情况时,playerOne变量对Player实例的引用被破坏。没有其他属性或变量仍然引用该Player实例,因此它被释放以释放其内存。就在这种情况发生之前,它的自动调节器会自动调用,并将其硬币返还给银行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值