zoukankan      html  css  js  c++  java
  • 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”
  • 相关阅读:
    关于TFS中WorkItem的探究
    Pro Android4 面试题归纳
    truncate 、delete、drop
    获取数据库中所有表的行数及其他信息
    【转】高手速成android开源项目【View篇】
    Can't create handler inside thread that has not called Looper.prepare()解决办法
    Android使用获取HTML
    .net操作EXCEL
    ASP.NET发送邮件
    如何使用 MasterPage
  • 原文地址:https://www.cnblogs.com/dson/p/4580082.html
Copyright © 2011-2022 走看看