1. 程式人生 > >[學習筆記]菜鳥教程Swift易忘知識點總結(五)

[學習筆記]菜鳥教程Swift易忘知識點總結(五)

繼承

子類

子類指的是在一個已有類的基礎上建立一個新的類。
為了指明某個類的超類,將超類名寫在子類名的後面,用冒號(:)分隔,語法格式如下:

	class SomeClass: SomeSuperclass {
	    // 類的定義
	}

重寫屬性

  • 可以提供定製的 getter(或 setter)來重寫任意繼承來的屬性,無論繼承來的屬性是儲存型的還是計算型的屬性。
  • 子類並不知道繼承來的屬性是儲存型的還是計算型的,它只知道繼承來的屬性會有一個名字和型別。在重寫一個屬性時,必需將它的名字和型別都寫出來。
  • 注意點:
    • 如果你在重寫屬性中提供了 setter,那麼你也一定要提供 getter。
    • 如果你不想在重寫版本中的 getter 裡修改繼承來的屬性值,你可以直接通過super.someProperty來返回繼承來的值,其中someProperty是你要重寫的屬性的名字。

重寫屬性觀察器

  • 可以在屬性重寫中為一個繼承來的屬性新增屬性觀察器。這樣一來,當繼承來的屬性值發生改變時,你就會監測到。

注意:你不可以為繼承來的常量儲存型屬性或繼承來的只讀計算型屬性新增屬性觀察器。

防止重寫

  • 可以使用 final 關鍵字防止它們被重寫。
  • 如果你寫了final方法,屬性或下標指令碼,在編譯時會報錯。
  • 可以通過在關鍵字class前新增final特性(final class)來將整個類標記為 final 的,這樣的類是不可被繼承的,否則會報編譯錯誤。

構造過程

  • 構造過程是為了使用某個類、結構體或列舉型別的例項而進行的準備過程。這個過程包含了為例項中的每個屬性設定初始值和為其執行必要的準備和初始化任務。
  • Swift 建構函式使用 init() 方法。
  • 與 Objective-C 中的構造器不同,Swift 的構造器無需返回值,它們的主要任務是保證新例項在第一次使用前完成正確的初始化。
  • 類例項也可以通過定義析構器(deinitializer)在類例項釋放之前執行清理記憶體的工作。

儲存型屬性的初始賦值

  • 類和結構體在例項建立時,必須為所有儲存型屬性設定合適的初始值。
  • 儲存屬性在構造器中賦值時,它們的值是被直接設定的,不會觸發任何屬性觀測器。
  • 儲存屬性在構造器中賦值流程:
    • 建立初始值。
    • 在屬性定義中指定預設屬性值。
    • 初始化例項,並呼叫 init() 方法。

內部和外部引數名

  • 跟函式和方法引數相同,構造引數也存在一個在構造器內部使用的引數名字和一個在呼叫構造器時使用的外部引數名字。

  • 然而,構造器並不像函式和方法那樣在括號前有一個可辨別的名字。所以在呼叫構造器時,主要通過構造器中的引數名和型別來確定需要呼叫的構造器。

  • 如果你在定義構造器時沒有提供引數的外部名字,Swift 會為每個構造器的引數自動生成一個跟內部名字相同的外部名。

  • 如果不為構造器的某個引數提供外部名字,可以使用下劃線_來顯示描述它的外部名。

可選屬性型別

  • 如果你定製的型別包含一個邏輯上允許取值為空的儲存型屬性,你都需要將它定義為可選型別optional type(可選屬性型別)。
  • 當儲存屬性宣告為可選時,將自動初始化為空 nil。

構造過程中修改常量屬性

  • 只要在構造過程結束前常量的值能確定,你可以在構造過程中的任意時間點修改常量屬性的值。
  • 對某個類例項來說,它的常量屬性只能在定義它的類的構造過程中修改;不能在子類中修改。

預設構造器

  • 預設構造器將簡單的建立一個所有屬性值都設定為預設值的例項

結構體的逐一成員構造器

  • 如果結構體對所有儲存型屬性提供了預設值且自身沒有提供定製的構造器,它們能自動獲得一個逐一成員構造器。
  • 我們在呼叫逐一成員構造器時,通過與成員屬性名相同的引數名進行傳值來完成對成員屬性的初始賦值。

值型別的構造器代理

構造器可以通過呼叫其它構造器來完成例項的部分構造過程。這一過程稱為構造器代理,它能減少多個構造器間的程式碼重複。

構造器代理規則

值型別 類型別
不支援繼承,所以構造器代理的過程相對簡單,因為它們只能代理給本身提供的其它構造器。 你可以使用self.init在自定義的構造器中引用其它的屬於相同值型別的構造器。 它可以繼承自其它類,這意味著類有責任保證其所有繼承的儲存型屬性在構造時也能正確的初始化。

類的繼承和構造過程

Swift 提供了兩種型別的類構造器來確保所有類例項中儲存型屬性都能獲得初始值,它們分別是指定構造器和便利構造器。

指定構造器 便利構造器
類中最主要的構造器 類中比較次要的、輔助型的構造器
初始化類中提供的所有屬性,並根據父類鏈往上呼叫父類的構造器來實現父類的初始化。 可以定義便利構造器來呼叫同一個類中的指定構造器,併為其引數提供預設值。你也可以定義便利構造器來建立一個特殊用途或特定輸入的例項。
每一個類都必須擁有至少一個指定構造器 只在必要的時候為類提供便利構造器
Init(parameters) { statements } convenience init(parameters) { statements }

構造器的繼承和過載

  • Swift 中的子類不會預設繼承父類的構造器。
  • 父類的構造器僅在確定和安全的情況下被繼承。
  • 當你重寫一個父類指定構造器時,你需要寫override修飾符。

類的可失敗構造器

如果一個類,結構體或列舉型別的物件,在構造自身的過程中有可能失敗,則為其定義一個可失敗構造器。
變數初始化失敗可能的原因有:

  • 傳入無效的引數值。
  • 缺少某種所需的外部資源。
  • 沒有滿足特定條件。

為了妥善處理這種構造過程中可能會失敗的情況。可以在一個類,結構體或是列舉型別的定義中,新增一個或多個可失敗構造器。其語法為在init關鍵字後面加添問號(init?)。

  • 值型別(如結構體或列舉型別)的可失敗構造器,對何時何地觸發構造失敗這個行為沒有任何的限制。
  • 類的可失敗構造器只能在所有的類屬性被初始化後和所有類之間的構造器之間的代理呼叫發生完後觸發失敗行為。

覆蓋一個可失敗構造器

  • 可以用子類的可失敗構造器覆蓋基類的可失敗構造器。
  • 可以用子類的非可失敗構造器覆蓋一個基類的可失敗構造器。
  • 可以用一個非可失敗構造器覆蓋一個可失敗構造器,但反過來卻行不通。
  • 一個非可失敗的構造器永遠也不能代理呼叫一個可失敗構造器。

可失敗構造器 init!

通常通過在init關鍵字後新增問號的方式(init?)來定義一個可失敗構造器,但也可以使用通過在init後面新增驚歎號的方式來定義一個可失敗構造器(init!)。

析構過程

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

析構過程原理

  • Swift 會自動釋放不再需要的例項以釋放資源。
  • Swift 通過自動引用計數(ARC)處理例項的記憶體管理。
  • 通常當你的例項被釋放時不需要手動地去清理。但是,當使用自己的資源時,你可能需要進行一些額外的清理。

語法
在類的定義中,每個類最多隻能有一個解構函式。解構函式不帶任何引數,在寫法上不帶括號:

deinit {
    // 執行析構過程
}

可選鏈

可選鏈(Optional Chaining)是一種可以請求和呼叫屬性、方法和子指令碼的過程,用於請求或呼叫的目標可能為nil。
可選鏈返回兩個值:

  • 如果目標有值,呼叫就會成功,返回該值
  • 如果目標為nil,呼叫將返回nil

多次請求或呼叫可以被連結成一個鏈,如果任意一個節點為nil將導致整條鏈失效。

可選鏈可替代強制解析

通過在屬性、方法、或下標指令碼的可選值後面放一個問號(?),即可定義一個可選鏈。

  • 可選鏈 ‘?’
    • 感嘆號(!)強制展開方法,屬性,下標指令碼可選鏈
  • ? 放置於可選值後來呼叫方法,屬性,下標指令碼
    • ! 放置於可選值後來呼叫方法,屬性,下標指令碼來強制展開值
  • 當可選為 nil 輸出比較友好的錯誤資訊
    • 當可選為 nil 時強制展開執行錯誤

連線多層連結

你可以將多層可選鏈連線在一起,可以掘取模型內更下層的屬性方法和下標指令碼。然而多層可選鏈不能再新增比已經返回的可選值更多的層。

  • 如果試圖通過可選鏈獲得Int值,不論使用了多少層連結返回的總是Int?。
  • 相似的,如果你試圖通過可選鏈獲得Int?值,不論使用了多少層連結返回的總是Int?。

對返回可選值的函式進行連結

可以通過可選連結來呼叫返回可空值的方法,並且可以繼續對可選值進行連結。