構造過程是使用類、結構體或枚舉類型的實例之前的準備過程。在新實例可用前必須執行這個過程,具體操作包括設置實例中每個存儲屬性的初始值和執行其他必須的設置或初始化工作。
存儲屬性的初始賦值
類和結構體在創建實例時,必須為所有存儲型屬性設置合適的初始值。存儲型屬性的值不能處于一個未知的狀態。
注意:當你為存儲型屬性設置默認值或者在構造器中為其賦值時,它們的值是被直接設置的,不會觸發任何屬性觀察者。
- 構造器
在創建某個特定類型的新實例時被調用。它的最簡形式類似于一個不帶任何參數的實例方法,已關鍵字init
命名。
init(){
//在此處執行構造過程
}
- 默認屬性值
可以在構造器中為存儲屬性設置初始值,同樣,可以在屬性聲明時為其設置默認值。
自定義構造過程
- 構造參數
可以在定義中提供構造參數,指定所需值得類型和名字。構造參數的功能和語法跟函數和方法的參數相同
struct A {
var num : Double;
init(value : Double) {
num = value;
}
init(newValue : Double) {
num = newValue * 2;
}
}
let a = A(value: 10);//num值為10;
let b = A(newValue: 10);//num值為20
- 不帶外部名的構造器參數
如果你不希望為構造器的某個參數提供外部名字,可以使用_
來顯示描述它的外部名。
struct A {
var num : Double;
init(_ value : Double) {
//隱藏外部名
num = value;
}
init(out newValue : Double) {
//out為外部名
num = newValue * 2;
}
}
let a = A(10);//num值為10;
let b = A(out: 10);//num值為20
- 可選屬性類型
如果你定制的類型包含一個邏輯上允許取值為空的存儲舒心,無論是因為它無法再初始化賦值,還是因為它在之后某個時間點可以賦值為空,你都需要將他定義為可選類型
。可選類型的屬性將自動初始化為nil
,表示這個屬性是有意在初始化時設置為空的。
class myclass{
var text: String
var response: String?
init(text: String) {
self.text = text
}
func ask() {
print(text)
}
}
let my = myclass(text: "geyang");
my.ask();
我們將屬性response
聲明為String?
類型,或者說是可選字符串類型
,當myclass
實例化時,它將自動賦值為nil
,表明此字符串暫時還沒有值。
默認構造器
如果結構體或類的所有屬性都有默認值,同事沒有自定義的構造器,那么Swift會給這些結構體或類提供一個默認構造器。這個默認構造器將簡單地創建一個所有屬性都設置默認值得實例。
class myclass{
var text: String = "how old are you";
var response: String?
}
let my = myclass();//默認構造器
由于該類中的所有屬性都有默認值,且它是沒有父類的基類,它將自動獲得一個為所有屬性設置默認值得默認構造器。
類的繼承和構造過程
指定構造器和便利構造器
指定構造器
是類中最主要的構造器,一個指定構造器將初始化類中提供的所有屬性,并根據父類鏈往上調用父類的構造器來實現父類的初始化。
每一個類都必須擁有至少一個指定構造器。
便利構造器
是類中比較次要的、輔助型的構造器,你可以定義便利構造器
來調用同一個類中的指定構造器
,并未其參數提供默認值,你也可以定義比那里構造器來創建一個特殊用途或特定輸入值的實例。
你應當只在必要的時候為類提供便利構造器
,比方說某種情況下通過使用便利構造器
來快捷調用某個指定構造器
,能夠節省更多開發時間并讓類的構造過程更清晰明了。指定構造器和遍歷構造器的語法
類的指定構造器的寫法跟值類型簡單構造器一樣:
init(paramters){
statements;
}
便利構造器也采用相同樣式的寫法,但需要在init
關鍵字之前防止convenience
關鍵字,并使用空格將它們倆分開:
convenience init (paramter){
statements;
}
- 類的構造器代理規則
為了簡化指定構造器和便利構造器之間的調用關系,Swift采用以下三條規則來限制構造器之間的代理調用:
1.指定構造器必須調用其直接父類的指定構造器
2.便利構造器必須調用同類中定義的其它構造器
3.便利構造器必須最終導致一個指定構造器被調用
一個更方便記憶的方式: - 指定構造器必須總是向上代理
- 便利構造器必須總是橫向代理
//便利構造器
class A{
var a : Int;
var b : Int;
//便利構造器
convenience init(b : Int){
self.init(a: 0, b: b);
}
//指定構造器
init(a : Int, b : Int) {
self.a = a;
self.b = b;
print("class ab init!");
}
}
可失敗的構造器
如果一個類,結構體或枚舉類型的對象,在構造過程中有可能失敗,則為定義一個可失敗的構造器,這里所指的“失敗”是指,如給構造器傳入無效的參數值,或缺少某種所需的外部資源,又或是不滿足某種必要的條件等。
為了妥善處理這種構造過程中可能會失敗的情況,你可以在一個類,結構體或枚舉類型定義中,添加一個或多個可失敗構造器,其語法為init
關鍵字后面添加問號(init
?)。
可失敗構造器會創建一個類型為自身類型的可選類型的對象,你通過return nil
語句來表明可失敗構造器在何種情況下“失敗”。
struct Animal {
let species: String
init?(species: String) {
if species.isEmpty { return nil }
self.species = species
}
}
定義了一個名為 Animal
的結構體,其中有一個名為 species
的 String
類型的常量屬性。同時該結構體 還定義了一個接受一個名為 species
的 String 類型參數的可失敗構造器
。這個可失敗構造器檢查傳入的參數是否 為一個空字符串。如果為空字符串,則構造失敗。否則,species
屬性被賦值,構造成功。
必要構造器
在類的構造器前添加required
修飾符表明所有該類別的子類都必須實現構造器
class SomeClass{
required init(){
}
}
在子類重寫父類的必要構造器時,必須在子類的構造器前也添加 required
修飾符,表明該構造器要求也應用于繼承鏈后面的子類。在重寫父類中必要的指定構造器時,不需要添加 override
修飾符。
通過閉包或函數設置屬性的默認值
如果某個存儲型屬性的默認值需要一些定制或設置,你可以使用閉包或全局函數為其提供定制的默認值。每當某
個屬性所在類型的新實例被創建時,對應的閉包或函數會被調用,而它們的返回值會當做默認值賦值給這個屬
性。
這種類型的閉包或函數通常會創建一個跟屬性類型相同的臨時變量,然后修改它的值以滿足預期的初始狀態,最
后返回這個臨時變量,作為屬性的默認值。
class SomeClass {
let someProperty: SomeType = {
// 在這個閉包中給 someProperty 創建 一個默認值
// someValue 必須和 SomeType 類型相同
return someValue
}()
}
注意閉包結尾的大括號后面接了一對空的小括號
。這用來告訴 Swift 立即執行此閉包
。如果你忽略了這對括 號,相當于將閉包本身作為值賦值給了屬性,而不是將閉包的返回值賦值給屬性。