Swift 構造過程 2

Swift中類的構造過程分爲兩個階段
1. 每個存儲屬性在它們被引入的類中會被指定一個初始值當所有的存儲屬性都有一個初始值後第二階段開始。
2. 在新實例使用之前,允許每個類進一步定製它們的存儲屬性。

類的代理規則

  1. 子類中的指定構造器必須調用父類的指定構造器(如果本身是父類可以忽略這條)
  2. 一個類的便利構造器必須調用這個類的其他構造器(橫向代理)
  3. 一個類的便利構造器必須最終調用這個類的指定構造器(向上代理)

類的指定構造器

父類的指定構造器

class Book {
    var boonName:String
    var bookPrice:Double
    var sendFriend:String {
        get {
            return boonName
        }
    }
    //指定構造器
    init(name:String,price:Double) {
        boonName = name;
        bookPrice = price
    }
}
  • 指定構造器的語法跟值類型構造器的語法相同

我們可以直接使用指定構造器來初始化一個實例如:var book3 = Book(name: "Like", price: 99)

子類的指定構造器

class MyBook:Book {
    var publicationDate:String

    //指定構造器
    init(name:String,price:Double,date:String) {
        publicationDate = date
        //規則1,指定構造器必須調用父類中的指定構造器
        super.init(name: name, price: price)
        bookPrice = 100
    }
}

MyBook這個類繼承自Book,對於子類的指定構造器有如下需要注意的:

  • 在子類的指定構造器中必須先給新引入的屬性賦值
  • 子類中的指定構造器必須代理父類中指定構造器super.init(...)
  • 子類中指定構造器必須在代理父類中的指定構造器後再設置繼承來的屬性值,在之前設置繼承的屬性值會在調用父類的指定構造器過程中被覆蓋的。

我們可以用MyBook的指定構造器初始化:var myBook5 = MyBook(name: "Five", price: 9.9, date: "1992")

類的便利構造器

對於Book這個類我們新增兩個便利構造器

    convenience init(freeBookName:String) {
        self.init(name: freeBookName, price: 0)
    }

    convenience init() {
        self.init(freeBookName:"Love China")
    }

對於MyBook這個類新增兩個便利構造器

    convenience init(myBookName:String,price:Double) {
        self.init(name: myBookName, price: price, date: "today")
        if bookPrice > 50 {
            self.bookPrice = 50
        }
    }
    convenience override init(name: String, price: Double) {
        self.init(myBookName: name, price: price)
        self.publicationDate = "2017"
    }

對於便利構造器我們有一下幾點:

  • 便利構造器必須先代理類中的其他構造器

  • 便利構造器必須最終代理到指定構造器

  • 在便利構造器必須先代理其他構造器再修改屬性值

  • 在構造器的第一階段完成前是無法使用self,無法調用實例方法。

  • 在便利構造器中我們必須在代理其他構造器後纔可以是有self,實例方法

    我們可以通過便利構造器來初始化一個實例:var myBook3 = MyBook(name: "World", price: 22),其用法與指定構造器一樣

類的可失敗構造器

對於Book這個類新增一個可失敗構造器

    init?(highPrice:Double) {
        if  highPrice < 100 { return  nil }
        self.boonName = "Price"
        self.bookPrice = highPrice
    }
  • 可失敗構造器的語法跟指定構造器的區別是在init後多了一個?
  • 可失敗構造器是指在構造過程當不滿足某些條件時返回nil值,在使用可失敗構造器初始化實例時返回的是一個可選
  • 如果在子類的非可失敗構造器中向上代理到父類的可失敗構造器,那麼需要對父類的可失敗構造器的代理結果強制解包

我們可以這樣來使用一個可失敗構造器:

if var book4 = Book(highPrice: 55) {
    book4.bookPrice
    book4.boonName
}else {
    var book5 = Book(highPrice: 120)
}

類的必要構造器

對於Book這個類,新增一個必要構造器

   required init (lowPrice:Double) {
        boonName = "Run"
        bookPrice = lowPrice
    }
  • 必要構造器需要在構造器前面添加關鍵字 required

  • 必要構造器要求子類也要重寫這個構造器,並且子類重寫的構造器也要添加關鍵字required

類的繼承與重寫

類的繼承

Swift裏面的類不會像OC裏面子類會自動繼承父類的構造方法,必須要滿足一定條件子類纔會繼承父類的構造方法

  • 當滿足前提:子類中新引入的屬性都有默認值時有下面的規則適用:

    • 如果子類沒有提供自己的指定構造器那麼它將自動繼承父類的指定構造器

    • 如果子類有提供所有父類的指定構造器的實現(可以是通過滿足前面條件繼承來的也可以是在子類中重寫的),那麼子類將默認繼承父類的便利構造器

類的重寫

子類可以對父類的構造器進行重寫,對於重寫有如下的一些總結:

  • 如果父類有必要構造器,子類必須重寫父類的必要構造器
  • 子類可以將父類的指定構造器重寫成子類的指定構造器,在構造器前加關鍵字override
  • 子類可以將父類的指定構造器重寫成爲子類的便利構造器,在構造器前加關鍵字convenience override
  • 子類嚴格意義來說是無法重寫父類的便利構造的,但是可以在子類中指定一個跟父類的便利構造器一下的構造器實現,這個構造器可以是子類的便利構造器也可以是子類的指定構造器,無論是哪種都不要有override關鍵字
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章