Swift 基礎學習(指定構造方法和便利構造方法)

/*
   繼承與構造方法
(1)指定構造與便利構造方法解析
(2)派生類的構造方法
(3)構造器鏈和安全檢查深入解析
(4)派生類的構造方法默認繼承
(5)構造方法的重寫
(6)必須構造方法
(7)析構方法
*/

/*
(1)指定構造與便利構造方法解析(Designated Initializers and Convenience Initializers)
*/
class AB {
    var a: Int
    var b: Int
    //指定構造方法, 不允許出現構造器代理,self.init(...)
    init(a: Int, b: Int) {
        self.a = a
        self.b = b
        print("Class AB init!")
    }

    //便利構造方法 -> 一定是通過調用其他的構造方法來實現初始化, self.init(...)
    convenience init(a: Int) {
//        self.a = a
//        b = 0
        self.init(a: a, b: 0)
    }
    convenience init() {
        //調用指定構造方法
//        self.init(a: 0, b: 0)
        //調用便利構造方法
        self.init(a: 0)
    }
}

/*
(2)派生類的構造方法
*/
class CD: AB {
    var c: Int
    var d: Int
    //構造方法默認是不會被繼承,基類的存儲屬性只能通過基類的構造方法來初始化
    //派生類引入的存儲屬性要先被初始化,然後再調用父類的構造方法對父類的屬性進行初始化
    //我們只能通過調用父類的指定構造方法來對父類的屬性進行初始化
    init(c: Int, d: Int) {
        self.c = c
        self.d = d
        super.init(a: 0, b: 0)
//        super.init(a: 0)
    }
}

/*
(3)構造器鏈-指定構造器和便利構造器之間的調用規則
總結:1.指定構造器必須調用其直接父類的指定構造器
    2.便利構造器必須調用同類中定義的其他構造器.(既可以是
指定構造器,也可以是便利構造器)
    3.便利構造器必須最終以調用一個指定構造器結束
指定構造器總是向上代理
便利構造器總是橫向代理
*/
class CD1: AB {
    var c: Int
    var d: Int

    //指定構造器
    init(c: Int, d: Int) {
        self.c = c
        self.d = d
        super.init(a: 0, b: 0)
        //        super.init(a: 0)
    }
    //便利構造器, 只能通過調用本類中的構造器完成初始化,不允許出現super.init(...)
    convenience init(a: Int, b: Int, c: Int, d: Int) {
        self.init(c: c, d: d)

    }
}

/*
(4)兩段式構造-構造過程可以劃分爲兩個階段
第一階段:確保所有的存儲屬性都初始化完畢
第二階段:對父類中的存儲屬性做進一步的處理.
作用:可以防止屬性在被初始化之前訪問,也可以防止屬性被另外
一個構造器意外的賦值.
*/
class A {
    var a: Int
    init(a: Int) {
        self.a = a
    }
}
class B: A {
    var b: Int
    init(a: Int, b: Int) {
        //派生類引入的屬性進行初始化
        print("類B第一階段初始化開始")
        self.b = b
        //父類的指定構造方法對父類的屬性進行初始化
        //只能在第一階段之後才能夠訪問
//        self.a = 1000
        super.init(a: a)

        print("類B第二階段初始化開始")
        if (b > 100) {
            self.a = 1000
        }
    }
}
class C: B {
    var c: Int
    init(a: Int, b: Int, c: Int) {
        //派生類引入的屬性進行初始化
        print("類C第一階段初始化開始")
        self.c = c
        //父類的指定構造方法對父類的屬性進行初始化
        super.init(a: a, b: b)

        print("類C第二階段初始化開始")
        if (c > 1000) {
            self.a = 1000
            self.b = 1000
        }
    }
}
class D: C {
    var d: Int
    init(a: Int, b: Int, c: Int, d: Int) {
        //派生類引入的屬性進行初始化
        print("類D第一階段初始化開始")
        self.d = d
        //父類的指定構造方法對父類的屬性進行初始化
        super.init(a: a, b: b, c: c)

        print("類D第二階段初始化開始")
        if (d > 1000) {
            self.a = 1000
            self.b = 1000
            self.c = 1000
        }
    }
}
var d = D(a: 0, b: 0, c: 0, d: 0)

/*
(5)派生類構造方法定義時的編譯器安全性檢查
a 首先應該將派生類引入的存儲屬性初始化,然後再向上代理父類
的制定構造方法.
b 首先調用父類中的制定構造器實現父類中屬性的初始化之後,才
可以訪問父類中的屬性.
c  在編寫便利構造方法時,我們首先要調用同類中的其他構造方
法,然後纔可以訪問
d  在第一階段完成之前,不能調用任何實例方法,不能訪問任何
父類中定義的存儲屬性,也不能引用self
*/
class D1: C {
    var d: Int
    init(a: Int, b: Int, c: Int, d: Int) {
        //派生類引入的屬性進行初始化
        print("類D第一階段初始化開始")
        self.d = d
        //父類的指定構造方法對父類的屬性進行初始化
        /*
        (1)不可以訪問父類中的屬性
        (2)不可以調用成員方法
        */
//        self.test()
        super.init(a: a, b: b, c: c)

        print("類D第二階段初始化開始")
        if (d > 1000) {
            self.a = 1000
            self.b = 1000
            self.c = 1000
        }
    }
    convenience init() {
        //首先應該調用同類中的其他構造方法之後,纔可以訪問屬性
        self.init(a: 0, b:0, c: 0, d:0)
        a = 9
        b = 3
        c = 4
        d = 90
    }
    func test() {

    }
}

/*
(6)重寫指定構造方法
是指"子類中構造方法與父類中的構造方法的參數列表一模一樣"
*/
class Human {
    let name: String
    var age: Int
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}
class Woman: Human {
    var haveBaby: Bool = false
    //派生類中定義一個構造方法,它跟父類中的某個指定構造方法一樣
//    override init(name: String, age: Int) {
//        haveBaby = false
//        super.init(name: name, age: age)
//    }

    init(name: String, age: Int, haveBaby: Bool) {
        self.haveBaby = false
        super.init(name: name, age: age)
    }
    convenience override init(name: String, age: Int) {
        self.init(name: name, age: age, haveBaby: false)
    }
}

/*

(7)重寫便利構造方法(其餘便利構造方法不存在重寫,只是爲了和上面的做對比,才起的這樣名)

*/
class Human1 {
    let name: String
    var age: Int
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
    convenience init() {
        self.init(name:"", age: 0)
    }
}
class Woman1: Human1 {
    var haveBaby: Bool = false
    //重寫成一個指定構造方法, 需要加上override關鍵字
    override init(name: String, age: Int) {
        haveBaby = false
        super.init(name: name, age: age)
    }
    //重寫一個便利構造方法,也需要加上override關鍵字
//    convenience override init(name: String, age: Int) {
//        self.init(name: name, age: age, haveBaby: false)
//    }

    init(name: String, age: Int, haveBaby: Bool) {
        self.haveBaby = false
        super.init(name: name, age: age)
    }
    convenience  init() {
        self.init(name: "" , age: 0, haveBaby: false)
    }
}
var w0 = Woman1()

/*
(8)構造器的自動繼承
a. 如果子類中沒有定義任何的構造方法,且子類中所有的存儲屬
性都有默認缺省值,會自動繼承父類中所有的構造方法(包括便利
構造方法);
b. 如果子類中只是重寫了父類中的某些(而不是全部)指定構造
方法,不管子類中的存儲屬性是否有缺省值,都不會繼承父類中的
其他構造方法;
c. 如果子類中重寫了父類中所有的指定構造方法,不管子類中的
存儲屬性是否有缺省值,都同時會繼承父類中所有的便利構造方
法;
*/
class XY {
    var x: Int
    var y: Int
    init(x: Int, y: Int) {
        self.x = x
        self.y = y
    }
    init(x: Int){
        self.x = x
        self.y = 0
    }
    convenience init() {
        self.init(x: 0, y: 0)
    }
}
//對應上面的a結論,沒有任何構造方法
class XYZ: XY {
    var z: Int = 10
    //對應上面的a結論,沒有任何構造方法
//    init(z: Int) {
//        self.z = z
//        super.init(x: 0, y: 0)
//    }
}
//對應上面的b結論,只是重寫部分構造方法
class XYZ1: XY {
    var z: Int = 10
    //    init(z: Int) {
    //        self.z = z
    //        super.init(x: 0, y: 0)
    //    }
    override init(x: Int, y: Int) {
        z = 10
        super.init(x: x, y: y)
    }

}
//對應上面的c結論,重寫父類所有構造方法
class XYZ2: XY {
    var z: Int = 10
    override init(x: Int, y: Int) {
        z = 10
        super.init(x: x, y: y)
    }

    override init(x: Int) {
        z = 10
        super.init(x: x, y: 0)
    }

}

var t0 = XYZ()
var t1 = XYZ2(x: 0)
var t2 = XYZ1(x: 0, y: 0)
print(t0.z)
print(t1.z)
print(t2.z)

/*
(9)必須構造器,構造方法所屬的類的後續子類必須也得實現這個構造方法
*/
class Some {
    var some: Int
    //必須實現方法
    required init() {
        some = 0
    }
}
class ChildOfSome: Some {
    var sub: Int
    init(sub: Int) {
        self.sub = sub
        super.init()
    }
    //子類也必須實現該方法
    required init() {
        sub = 0
        super.init()
    }
}
發佈了80 篇原創文章 · 獲贊 8 · 訪問量 25萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章