Swift學習筆記 二十五 析構過程

2021-09-26 05:16:25 字數 3550 閱讀 8610

析構器只適用於類型別,當乙個類的實例被釋放之前,析構器會被立即呼叫。析構器⽤關鍵字 deinit 來標示,類似於構造器要用

init 來標示。

swift 會自動釋放不再需要的實例以釋放資源。如《自動引用計數》章節中所講述,swift 通過自動引用計數(arc) 處理理實例的

記憶體管理。通常當你的實例被釋放時不需要手動地去清理。但是,當使用自己的資源時,你可能需要進⾏⼀些額外的清理。例

如,如果建立了乙個自定義的類來開啟乙個檔案,並寫入一些資料,你可能需要在類例項被釋放之前⼿動去關閉該檔案。

在類的定義中,每個類最多只能有乙個析構器,⽽且析構器不帶任何引數和圓括號,如下所示:

deinit {

// 執⾏析構過程

析構器是在例項釋放發生前被自動呼叫的。你不能主動呼叫析構器。子類繼承了父類的析構器,並且在子類析構器實現的最後,

⽗類的析構器會被自動呼叫。即使子類沒有提供自己的析構器,⽗類的析構器也同樣會被呼叫。

因為直到例項的析構器被呼叫後,實例才會被釋放,所以析構器可以訪問實例的所有屬性,並且可以根據那些屬性可以修改它的

⾏為(比如查詢乙個需要被關閉的檔案)。

這是乙個析構器實踐的例子。這個例子描述了乙個簡單的遊戲,這里定義了兩種新型別,分別是 bank 和player 。 bank 類管理

一種虛擬硬幣,確保流通的硬幣數量永遠不可能超過 10,000。在遊戲中有且只能有乙個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 物件會返回乙個比請求時小的數

字(如果 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")

// 列印「a new player has joined the game with 100 coins」

print("there are now \(bank.coinsinbank) coins left in the bank")

// 列印「there are now 9900 coins left in the bank」

建立乙個 player 實例的時候,會向 bank 物件申請得到 100 個硬幣,前提是有足夠的硬幣可用。這個 player 實例儲存在乙個名為 

playerone 的可選型別的變量中。這⾥使⽤了乙個可選型別的變量,是因為玩家可以隨時離開遊戲,設定為可選使你可以追蹤玩

家當前是否在遊戲中。

因為 playerone 是可選的,所以在訪問其 coinsinpurse 屬性來列印錢包中的硬幣數量和呼叫 win(coins:) ⽅法時,使用感嘆號( ! )

強制解包:

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 筆記 十五 析構過程 ARC

析構過程 析構過程是構造過程的逆向過程,當乙個類的例項被釋放的時候,在記憶體中消失前,析構器會被呼叫。原型 deinit 由於swift是arc管理記憶體,所以析構過程已經不像c 那麼重要了。class myclass deinit var myinstance myclass?myclass pr...

析構 Swift學習筆記(十八)

注 本文為自己學習the swift programming language的筆記,其中的例子為引用原書和其他博文或自己原創的。每個例子都會批註一些實踐過程中的經驗或思考總結。1.基礎 析構過程 deinitialization 由析構函式 deinitializer 完成,類的例項在被 資源之前...

第二十五周學習筆記

本次實驗使用的是github上別人公開的 並參考了及其配套博文 為了構建截圖生成latex 的模型,首先需要準備資料,資料是 於arxiv.org上的 中公式latex原始碼和pdf截圖對 資料集 分為訓練集76053對 latex原始碼對和測試集9447對,一對示例資料如下 本文需要解決的問題是從...