about 1 year ago

Initialization

Classes 與 structures 在建立 instance 時,所有的 property 一定都需要有初始值,
若在宣告 property 時未給予預設值,就必須在 initializer 內來設定。

Initializer 宣告

基本宣告

class MyClass {
    var property: Int
    var property2 = 123
    init () {
        property = 123
    }
}

客製化宣告

class MyClass {
    var property: Int
    init (para: Int) {
        property = para
    }
}

預設 initializer
若 property 全都有預設值,就會自動產生一個不需帶任何參數的 initializer。
但如果有宣告其他的 initializer,這個 initializer 就不會自動產生。

Structures 的 initializer

之前有介紹到,如果 structures 有 property,會自動產生帶有參數的 initializer。

struct MyStruct {
    var property: Int
}
let s = MyStruct(property: 123)

Designated initializers & convenience initializers

Designated initializers 是 class 內最主要的初始化方法,
class 內至少要有一個 designated initializer。
Convenience initializers 是 class 內次要的初始化方法,
class 內可以沒有 convenience initializers。
宣告方法
Designated initializers

class MyClass {
    init() {
    }
}

Convenience initializers

class MyClass {
    convenience init () {
    }
}

重點規則
每個 subclass 內的 designated initializers 一定要呼叫 superclass 的 designated initializers。

class MyClass {
    init() {
    }
    init(para: String) {
    }
}
class MyClass2: MyClass {
    init(para: Int) {
        super.init(para: 123")
    }
}

每個 convenience initializers 一定要呼叫同一個 class 內其他的 initializers。

class MyClass {
    init() {
    }
    convenience init(para: Int) {
        self.init()
    }
}

Convenience initializers 最後一定要呼叫到 designated initializers。

class MyClass {
}
class MyClass2: MyClass {
    init(para: String) {
    }
    convenience init(para: Int) {
        self.init(para: 123")
    }
    convenience init(para: Int, para2: Int) {
        self.init(para: para)
    }
}

繼承 initializers

Swift 的 subclass 並不會繼承 superclass 的 initializers。
但如果 subclass 沒有宣告任何 designated initializers,
subclass 會自動繼承 superclass 所有的 initializers。

class MyClass {
    init(para: Int) {
    }
}
class MyClass2: MyClass {
}
let c = MyClass2(para:123)

如果 subclass 重新宣告 superclass 全部的 designated initializers,
那麼 subclass 就會自動繼承 superclass 所有的 convenience initializers。

class MyClass {
    init() {
    }
    init(para: Int) {
    }
    convenience init(para: String) {
    }
}
class MyClass2: MyClass {
    override init(para: Int) {
        super.init()
    }
}
let c = MyClass2(para:123")

Fallible initializers

可以讓初始化後回傳 Optionals 的 nil,代表初始化失敗。

class MyClass {
    init?(para: String) {
        if para.isEmpty { return nil }
    }
}

也可以讓 subclass override superclass 的 fallible initializers,
變成 non fallible initializers。

class MyClass {
    init() {
    }
    init?(para: String) {
        if para.isEmpty {return nil}
    }
}
class MyClass2: MyClass {
    override init(para: String) {
        super.init()
    }
}

必要 initializer

如果 subclass 有定義自己的 designated initializers,
那 subclass 就必須一定要實作 superclass 上有加 required 的 initializer。

class MyClass {
    required init(para: String) {
    }
}
class MyClass2: MyClass {
    init() {
    }
    required init(para: String) {
    }
}

透過 closure 設定 property 初始值

可以直接透過 closure 來設定 property,在 instance 建立時,會同時呼叫這個 closure 來設值,
要記住切勿在此 closure 內使用其他的 property,因為這時候的 instance 尚未被建立,
其他的 property 可能還沒被初始化。

class MyClass {
    let para = { ()->String in
        return 123
    }()
}

Deinitialization

Deinitializer 會在 instance 被 dealloc 時被自動呼叫,也沒有任何方法能夠主動去呼叫。

class MyClass {
    deinit {
    print("deinit")
  }
}
let c = MyClass()
c = nil
← iOS Swift : Inheritance iOS Swift : Automatic Reference Counting →