Swift Review#28[析構Deinitialization]

影山小麥機
6 min readJul 6, 2021

--

前言

我們花了一些篇幅理解了建構化、建構器的原理與作法,尤其花了泰半描述參考型別分類-類別實作的相關作法、類別繼承中,父類別、子類別中建構器的運作,而今日要花另一些時間來描述所謂的「析構」

不過,原先這篇應該是#29,但似乎先理解ARC,自動參考計數會是比較好的一個選項,尤其對於析構這件事情來說,故,先完成了#29。但不論如何,我們繼續往下看。

正文

引自《The Swift of Programming Language》中文版

析構原理

在一個類別的實例被釋放之前,析構函式被立即呼叫。用關鍵字deinit來標示析構函式,類似於初始化函式用init來標示。析構函式只適用於類型別。

Swift 會自動釋放不再需要的實例以釋放資源。如自動引用計數那一章描述,Swift 通過自動引用計數(ARC)處理實例的內存管理。通常當你的實例被釋放時不需要手動地去清理。但是,當使用自己的資源時,你可能需要進行一些額外的清理。

100Days of Swift的文章亦指出

The job of deinitializers is to tell us when a class instance was destroyed. For structs this is fairly simple: the struct is destroyed when whatever owns it no longer exists. So, if we create a struct inside a method and the methods ends, the struct is destroyed.

析構器的工作是告訴我們什麼時候一個類別實例會被破壞。對於結構來說,這非常的簡單:結構的廢棄是當我們的擁有者再存在,所以,如果我們創造了一個方法在結構裡面,而方法結束後,結構也隨之廢棄。

Behind the scenes Swift performs something called automatic reference counting, or ARC. ARC tracks how many copies of each class instance exists: every time you take a copy of a class instance Swift adds 1 to its reference count, and every time a copy is destroyed Swift subtracts 1 from its reference count. When the count reaches 0 it means no one refers to the class any more, and Swift will call its deinitializer and destroy the object.

在螢幕後,Swift呈現了某件事情:自動參考計數,或稱之為ARC,ARC的功能是在追蹤有多少個類別的實例存在,一旦你複製出一個實例,ARC就會自動的在參考計數上加一,以及每次一個複製廢棄後,Swift就會從實例計算中減去1。當計算達到零時,意指沒有對象可從類別中再找到東西了,Swift就會呼叫析構器去廢棄物件。

總而言之,析構在其目的上,是為了將不需要的實例資源釋放。而Swift有它自己的實例內存管理的方法,通常實例產生時,不會需要開發者動手去清理,但我們仍有可能碰到需要清理的時候,尤其是我們使用自己的資源,而常見者如:

如果創建了一個自定義的類別來打開一個文件,並寫入一些資料,你可能需要在類別實例被釋放之前關閉該文件。

上述之文字所及,也就是說,析構的使用,是基於類別實體被釋放前的運作機制,我們通常創建了一個類別後,底下會有建構器,但為了避免資料一直處於打開狀態,所以希望在建構器後,能將那些引入的資料關閉,這個時候,就需要析構器來扮演這樣的角色。

析構器

在類別的定義中,每個類別最多只能有一個析構函式。析構函式不帶任何參數,在寫法上不帶括號:

deinit {
// 執行析構過程
}

析構函式是在實例釋放發生前一步被自動呼叫。

因此,析構器有一些特點:

  1. 不允許主動呼叫自己的析構函式。
  2. 子類別繼承了父類別的析構函式,並且在子類別析構函式實作的最後,父類別的析構函式被自動呼叫。
  3. 即使子類別沒有提供自己的析構函式,父類別的析構函式也總是被呼叫。

因為直到實例的析構函式被呼叫時,實例才會被釋放,所以析構函式可以存取所有請求實例的屬性,並且根據那些屬性可以修改它的行為(比如查找一個需要被關閉的文件的名稱)。

就以下列舉例來說:

其實析構器就是在類別結束的時候,作為是將整個結構的內存清空的一種存在。

總之,關於析構器這件事情,在100Days of Swift中Paul Hudson在文章的結尾處是這樣說的:

So, the simple reason for why structs don’t have deinitializers is because they don’t need them: each struct has its own copy of its data, so nothing special needs to happen when it is destroyed.

所以,結構不需要析構器的最簡單理由,是因為他們不需要它:每個結構都有自己擁有的複製的資料,所以當它們被銷毀的時候,沒有什麼特別需要注意的(這裡指結構為什麼沒有析構器)

You can put your deinitializer anywhere you want in your code, but I love this quote from Anne Cahalan: “Code should read like sentences, which makes me think my classes should read like chapters. So the deinitializer goes at the end, it’s the ~fin~ of the class!”

你可以讓你的析構器隨便放置,但我比較傾心於Anne Cahalan所說的:程式碼應該讀起來像句子,這樣讓我覺得我的類別讀起來像是讀一個篇章。所以,析構器放置在最底,就像是:這個篇章的結尾

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

影山小麥機
影山小麥機

Written by 影山小麥機

本職為Mobile工程師,熱愛分享視野,也樂意站在ChatGPT的肩膀上。訂閱小麥機,收割技術、職涯、人生的難題。

No responses yet

Write a response