Swift -- 構造過程

構造過程是使用類、結構體或枚舉類型的實例之前的準備過程。在新實例可用前必須執行這個過程,具體操作包括設置實例中每個存儲屬性的初始值和執行其他必須的設置或初始化工作。

存儲屬性的初始賦值

類和結構體在創建實例時,必須為所有存儲型屬性設置合適的初始值。存儲型屬性的值不能處于一個未知的狀態。
注意:當你為存儲型屬性設置默認值或者在構造器中為其賦值時,它們的值是被直接設置的,不會觸發任何屬性觀察者。

  • 構造器
    在創建某個特定類型的新實例時被調用。它的最簡形式類似于一個不帶任何參數的實例方法,已關鍵字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 的結構體,其中有一個名為 speciesString 類型的常量屬性。同時該結構體 還定義了一個接受一個名為 species 的 String 類型參數的可失敗構造器。這個可失敗構造器檢查傳入的參數是否 為一個空字符串。如果為空字符串,則構造失敗。否則,species 屬性被賦值,構造成功。

必要構造器

在類的構造器前添加required修飾符表明所有該類別的子類都必須實現構造器

class SomeClass{
      required init(){
      }
}

在子類重寫父類的必要構造器時,必須在子類的構造器前也添加 required修飾符,表明該構造器要求也應用于繼承鏈后面的子類。在重寫父類中必要的指定構造器時,不需要添加 override修飾符。

通過閉包或函數設置屬性的默認值

如果某個存儲型屬性的默認值需要一些定制或設置,你可以使用閉包或全局函數為其提供定制的默認值。每當某
個屬性所在類型的新實例被創建時,對應的閉包或函數會被調用,而它們的返回值會當做默認值賦值給這個屬
性。
這種類型的閉包或函數通常會創建一個跟屬性類型相同的臨時變量,然后修改它的值以滿足預期的初始狀態,最
后返回這個臨時變量,作為屬性的默認值。

class SomeClass {
    let someProperty: SomeType = {
    // 在這個閉包中給 someProperty 創建 一個默認值 
   // someValue 必須和 SomeType 類型相同
    return someValue
}() 
}

注意閉包結尾的大括號后面接了一對空的小括號。這用來告訴 Swift 立即執行此閉包。如果你忽略了這對括 號,相當于將閉包本身作為值賦值給了屬性,而不是將閉包的返回值賦值給屬性。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,963評論 6 542
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,348評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,083評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,706評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,442評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,802評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,795評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,983評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,542評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,287評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,486評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,030評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,710評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,116評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,412評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,224評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,462評論 2 378

推薦閱讀更多精彩內容

  • ?構造過程是使用類、結構體或枚舉類型一個實例的準備過程。在新實例可用前必須執行這個過程,具體操作包括設置實例中每個...
    EndEvent閱讀 647評論 0 3
  • 本章將會介紹 存儲屬性的初始賦值自定義構造過程默認構造器值類型的構造器代理類的繼承和構造過程可失敗構造器必要構造器...
    寒橋閱讀 778評論 0 0
  • 構造過程是為了使用某個類、結構體或枚舉類型的實例而進行的準備過程。這個過程包含了為實例中的每個屬性設置初始值和為其...
    零度_不結冰閱讀 259評論 0 0
  • 構造過程是使用類、結構體或枚舉類型的實例之前的準備過程。在新實例可用前必須執行這個過程,具體操作包括設置實例中每個...
    莽原奔馬668閱讀 697評論 0 3
  • Swift 構造過程 step 1. 首先從Objective-C的構造開始說起 在Objective-C的構造函...
    小梁同學閱讀 1,671評論 0 2