Swift 構造與析構

來源:互聯網
上載者:User

標籤:body   手動   判斷   自動產生   red   子類   mes   引用計數   建立   

前言
  • 與 OC 一樣,Swift 中也存在構造和析構過程。不同的是,OC 中的構造方法和析構方法只是普通的方法,而 Swift 中構造器和析構器是一種特殊的結構。
1、構造器
  • 在 Swift 中,類或者結構體在初始化時必須保證它們中包含的所有屬性都被初始化,構造器用來初始化類或者結構體中的屬性,在形式上構造器和方法很像,但是它並不是一個方法。

    • 聲明構造器不需要 func 關鍵字。
    • 和 OC 類似,在 Swift 中使用 init 表義構在器。
    • 在一個類或者結構體中可以有多個構造器,所有的構造器都叫 init,系統通過重載的特性來判斷使用那個構造器。
    • 在參數命名上可以使用和屬性相同的名稱做對應,如果構造器中參數的名稱和屬性的名稱相同,則使用 self 關鍵字標示屬性。
    • 在類中 Swift 提供三種構造器來做初始化:指定構造器、便利構造器和可失敗構造器。

      // 指定構造器init(參數名1: 參數類型, 參數名2: 參數類型, ...) {    statements}
      // 便利構造器convenience init(參數名1: 參數類型, 參數名2: 參數類型, ...) {    statements}
      // 可失敗構造器init?(參數名1: 參數類型, 參數名2: 參數類型, ...) {    statements}
  • 在某些情況下系統會自動產生一個構造器。

    • 如果是在某個類中,當類中的所有屬性都有初始值,並且類中沒有定義構造器時,就會得到一個沒有參數的構造器 init()
    • 如果是在結構體中,當類中的所有屬性都有初始值,並且結構體中沒有定義構造器時,就會得到一個預設將所有屬性作為參數的構造器。
  • 使用構造器時注意事項。

    • 在任何構造器完成時,必須保證所有的屬性都被初始化了,即便可選型屬性的值是 nil,也算它有值。
    • 調用類中的方法和屬性必須在初始化完成之後才能進行。
  • 在 Swift 中採用繼承式初始化方式。

    • 父類和子類的構造器進行互動時,是通過各自的指定構造器進行互動的。
    • 便捷構造器只關心本類中的其它構造器,而不關心父類或者子類的構造器。
    • 如果在構造器前加上 required 關鍵字,那麼這個類的子類就必須實現它的這個構造器。
1.1 指定構造器
  • 指定構造器包含系統自動產生的構造器和除便利構造器及可失敗構造器之外的所有構造器,是預設的初始化方法。

    • 指定構造器必須在 init 中調用父類的指定構造器,而不能調用其自身的其它構造器。

      init(參數名1: 參數類型, 參數名2: 參數類型, ...) {    statements}
  • 如果沒有在類中實現任何指定構造器,那麼將繼承父類中的所有指定構造器。

    // 父類class Transport {    var scope = ""    init() {}                                       // 無參數指定構造器    init(str: String) {                             // 有一個參數的指定構造器        self.scope = str    }}
    // 子類class Car: Transport {                                                    // 沒有在類中實現任何指定構造器}
    // 使用let myCar = Car()                                   // 使用了父類中的無參數構造器let myNewCar = Car(str: "ludi")                     // 使用父類中有一個參數的構造器
  • 一旦在子類中建立了自己的指定構造器,將不能再使用父類中的構造器,並且子類中的指定構造器聲明中需要調用父類中的某個指定構造器。

    // 父類class Transport {    var scope = ""    init() {}                                       // 無參數指定構造器    init(str: String) {                             // 有一個參數的指定構造器        self.scope = str    }}
    // 子類class Car: Transport {    var wheel = "pulisitong"    init(scope: String, wheel: String) {            // 建立自己的指定構造器        super.init()                                // 指定構造器必須調用父類的指定構造器        self.scope = scope        self.wheel = wheel    }}
    // 使用let myCar = Car(scope: "ludi", wheel: "miqilin")    // 此時不能使用父類中無參或者有一個參數的構造器
1.2 便利構造器
  • 調用其它構造器的構造器就叫便利構造器。

    • 便利構造器必須調用一個其它的構造器。
    • 便利構造器必須直接或者間接調用指定構造器之後才能訪問其它值,它還可以通過調用其它便利構造器來間接調用指定構造器。
    • 如果一個便利構造器想要調用指定構造器,則它必須並且只能調用本類中的指定構造器,而不能調任何父類的構造器。

      convenience init(參數名1: 參數類型, 參數名2: 參數類型, ...) {    statements}
  • 如果子類中重寫了父類中所有的指定構造器,那麼將繼承父類中所有的便利構造器。

    // 父類class Transport {    var scope = ""    init() {}                                       // 無參數指定構造器    init(str: String) {                             // 有一個參數的指定構造器        self.scope = str    }    convenience init(scope: String) {               // 便利構造器        self.init(str: scope)                       // 調用自身類的指定構造器    }}
    // 子類class Car: Transport {    override init() {                               // 重寫父類指定構造器        super.init()                                // 指定構造器必須調用父類的指定構造器    }    override init(str: String) {                    // 重寫父類指定構造器        super.init()                                // 指定構造器必須調用父類的指定構造器        self.scope = "Car" + str    }}
    // 使用let myCar = Car(scope: "ludi")                      // 調用父類的便利構在器
1.3 可失敗構造器
  • 有一些初始化方法允許失敗,並且返回 nil

    • 可失敗構造器的定義中 init 後面跟著一個 ?

      init?(參數名1: 參數類型, 參數名2: 參數類型, ...) {    statements}
  • 通常面對這種可失敗構造器建議使用 if-letguard-let-else 結構,如果初始化成功就執行操作,否則就做其它操作。

    • if-let 結構

      if let image = UIImage(named: "test") {    // 執行與 image 有關的代碼} else {    // 執行與 image 無關的代碼}
    • guard-let-else 結構

      guard let image = UIImage(named: "test") else {    // 執行與 image 無關的代碼}// 執行與 image 有關的代碼
1.4 匿名構造器
  • 有些時候某種對象的子類我們只建立一次,沒有必要專門寫一個構造器。

    • 使用閉包的形式建立一個匿名的構造器,閉包後需要加 (),用來告訴 Swift 需要立刻執行此閉包,否則會把閉包本身作為值賦給了屬性。

      let button: UIButton = {    let button = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 100))    button.backgroundColor = UIColor.white    return button}()
    • 使用其它對象方法建立一個匿名的構造器。

      let someArray = ["1", "2", "3"]let someString = someArray.joined(separator: ", ")print(someString)                 // 1, 2, 3
2、析構器
  • 和構造器對應,Swift 還提供了析構器,用於釋放對象。

    • 析構器只適用於類。
    • 一個類中只能定義一個析構器。
    • 析構器的定義和構造器很像,使用關鍵字 deinit,並且析構器沒有參數。

      deinit() {    // 執行析構過程}
  • 在把對象設定為 nil 時,系統會自動調用析構器。

    deinit {    self.conn.close()    self.conn = nil}
  • 由於 Swift 中引入了自動引用計數(ARC),因此不需要讀者手動管理記憶體,但在使用一些自己的資源的時候,需要使用析構器。

    • 比如我要建立一個資料庫訪問類,在初始化時開啟連結,如果程式退出,串連不釋放,資源就會浪費。
  • 實值型別沒有析構是因為實值型別不會出現 “共用”,每個實值型別只有一個擁有者。

    • 比如某個方法,實值型別會在其擁有者被系統回收時一同回收,我們不需要在意實值型別的生命週期。

Swift 構造與析構

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.