Day12 構(gòu)造過程

1、存儲屬性的初始賦值

    init() {
        // 在此處執(zhí)行構(gòu)造過程
    }
    //eg:
    
    struct Fahrenheit {
        var temperature: Double
        init() {
            temperature = 32.0
        }
    }
    var f = Fahrenheit()
    print("The default temperature is \(f.temperature)° Fahrenheit")
    //The default temperature is 32.0° Fahrenheit
    
    //你可以使用更簡單的方式在定義結(jié)構(gòu)體 Fahrenheit 時為屬性 temperature 設置默認值:
    struct Fahrenheit1 {
        var temperature = 32.0
    }

2、自定義構(gòu)造過程

構(gòu)造參數(shù)

下面例子中定義了一個包含攝氏度溫度的結(jié)構(gòu)體 Celsius 。它定義了兩個不同的構(gòu)造器: init(fromFahrenheit:) 和 init(fromKelvin:) ,二者分別通過接受不同溫標下的溫度值來創(chuàng)建新的實例:

    struct Celsius {
        var temperatureInCelsius: Double
        init(fromFahrenheit fahrenheit: Double) {
            temperatureInCelsius = (fahrenheit - 32.0) / 1.8
        }
        init(fromKelvin kelvin: Double) {
            temperatureInCelsius = kelvin - 273.15
        } }
    //自定義初始化
    let boilingPointOfWater = Celsius(fromFahrenheit: 212.0)
    // boilingPointOfWater.temperatureInCelsius 是 100.0
    let freezingPointOfWater = Celsius(fromKelvin: 273.15)
    // freezingPointOfWater.temperatureInCelsius 是 0.0

第一個構(gòu)造器擁有一個構(gòu)造參數(shù),其外部名字為 fromFahrenheit ,內(nèi)部名字為 fahrenheit ;
第二個構(gòu)造器也擁 有一個構(gòu)造參數(shù),其外部名字為 fromKelvin ,內(nèi)部名字為 kelvin

不帶外部名的構(gòu)造器參數(shù)

如果你不希望為構(gòu)造器的某個參數(shù)提供外部名字,你可以使用下劃線( _ )來顯式描述它的外部名,以此重寫上面所說的默認行為。

    struct Celsius1 {
        var temperatureInCelsius: Double
        init(fromFahrenheit fahrenheit: Double) {
            temperatureInCelsius = (fahrenheit - 32.0) / 1.8
        }
        init(fromKelvin kelvin: Double) {
            temperatureInCelsius = kelvin - 273.15
        }
        init(_ celsius: Double){
            temperatureInCelsius = celsius
        }
    }
    let bodyTemperature = Celsius1(37.0)
    // bodyTemperature.temperatureInCelsius 為 37.0

可選屬性類型

下面例子中定義了類 SurveyQuestion ,它包含一個可選字符串屬性 response

    class SurveyQuestion {
        var text: String
        var response: String?//可選類型
        init(text: String) {
            self.text = text
        }
        func ask() {
            print(text)
        }
    }
    let cheeseQuestion = SurveyQuestion(text: "Do you like cheese?")
    //調(diào)用函數(shù) ask() 方法
    cheeseQuestion.ask()
    // 打印 "Do you like cheese?"
    cheeseQuestion.response = "Yes, I do like cheese."

構(gòu)造過程中常量屬性的修改
eg:

    class SurveyQuestion1 {
        let text: String  //常量只被初始化一次
        var response: String?
        init(text: String) {
            self.text = text
        }
        func ask() {
            print(text)
        } }
    let beetsQuestion = SurveyQuestion1(text: "How about beets?")
    beetsQuestion.ask()
    // 打印 "How about beets?"
    beetsQuestion.response = "I also like beets. (But not with cheese.)"

3、默認構(gòu)造器

如果結(jié)構(gòu)體或類的所有屬性都有默認值,同時沒有自定義的構(gòu)造器,那么 Swift 會給這些結(jié)構(gòu)體或類提供一個默 認構(gòu)造器(default initializers)。這個默認構(gòu)造器將簡單地創(chuàng)建一個所有屬性值都設置為默認值的實例。

下面例子中創(chuàng)建了一個類 ShoppingListItem ,它封裝了購物清單中的某一物品的屬性:名字( name )、數(shù)量( quantity )和購買狀態(tài) purchase state :

    class ShoppingListItem {
        var name: String?
        var quantity = 1
        var purchased = false
    }
    var item = ShoppingListItem()
    print("name is \(item.name)")//name is nil

4、類的繼承和構(gòu)造過程

類里面的所有存儲型屬性——包括所有繼承自父類的屬性——都必須在構(gòu)造過程中設置初始值。

指定構(gòu)造器和便利構(gòu)造器

指定構(gòu)造器是類中最主要的構(gòu)造器。一個指定構(gòu)造器將初始化類中提供的所有屬性,并根據(jù)父類鏈往上調(diào)用父類的構(gòu)造器來實現(xiàn)父類的初始化

便利構(gòu)造器是類中比較次要的、輔助型的構(gòu)造器。你可以定義便利構(gòu)造器來調(diào)用同一個類中的指定構(gòu)造器,并為其參數(shù)提供默認值。你也可以定義便利構(gòu)造器來創(chuàng)建一個特殊用途或特定輸入值的實例

    //指定構(gòu)造器和便利構(gòu)造器的語法
    /*
    init(parameters) {
        statements
    }
    
     convenience init(parameters) {
         statements
     }
     
    */

類的構(gòu)造器代理規(guī)則

[? 指定構(gòu)造器必須總是向上代理
? 便利構(gòu)造器必須總是橫向代理]

構(gòu)造器的繼承和重寫

跟 Objective-C 中的子類不同,Swift 中的子類默認情況下不會繼承父類的構(gòu)造器。
Swift 的這種機制可以防止一個父類的簡單構(gòu)造器被一個更精細的子類繼承,并被錯誤地用來創(chuàng)建子類的實例。

重寫父類方法 要添加override 關(guān)鍵字
eg:

    class Vehicle {
        var numberOfWheels = 0
        var description: String {
            return "\(numberOfWheels) wheel(s)"
        }
    }
    
    let vehicle = Vehicle()
    print("Vehicle: \(vehicle.description)")
    // Vehicle: 0 wheel(s)
    
    //下面例子中定義了一個 Vehicle 的子類 Bicycle :
    class Bicycle: Vehicle {
        override init() {
            super.init()
            numberOfWheels = 2
        }
    }
    
    let bicycle = Bicycle()
    print("bicycle: \(bicycle.description)")
    //bicycle: 2 wheel(s)

指定構(gòu)造器和便利構(gòu)造器實踐

    class Food {
        var name: String
        init(name: String) {
            self.name = name
        }
        convenience init() {
            self.init(name: "[Unnamed]")
        }
    }
    
    let namedMeat = Food(name: "Bacon")
    // namedMeat 的名字是 "Bacon”
    
    let mysteryMeat = Food()
    // mysteryMeat 的名字是 [Unnamed]
    
    class RecipeIngredient: Food {
        var quantity: Int
        init(name: String, quantity: Int) {
            self.quantity = quantity
            super.init(name: name)
        }
        override convenience init(name: String) {
            self.init(name: name, quantity: 1)
        }
    }
    
    let oneMysteryItem = RecipeIngredient()
    let oneBacon = RecipeIngredient(name: "Bacon")
    let sixEggs = RecipeIngredient(name: "Eggs", quantity: 6)
    
    class ShoppingListItem1: RecipeIngredient {
        var purchased = false
        var description: String {
            var output = "\(quantity) x \(name)"
            output += purchased ? " ?" : " ?"
            return output
        }
    }
    
    var breakfastList = [
        ShoppingListItem1(),
        ShoppingListItem1(name: "Bacon"),
        ShoppingListItem1(name: "Eggs", quantity: 6),
        ]
    breakfastList[0].name = "Orange juice"
    breakfastList[0].purchased = true
    for item in breakfastList {
        print(item.description)
    }
    // 1 x orange juice ?
    // 1 x bacon ?
    // 6 x eggs ?

可失敗構(gòu)造器

你可以在一個類,結(jié)構(gòu)體或是枚舉類型的定義中,添加一個或 多個可失敗構(gòu)造器。其語法為在 init 關(guān)鍵字后面添加問號( init? )

    struct Animal {
        let species: String
        init?(species: String) {
            if species.isEmpty { return nil }
            self.species = species
        }
    }

你可以通過該可失敗構(gòu)造器來構(gòu)建一個 Animal 的實例,并檢查構(gòu)造過程是否成功:

    let someCreature = Animal(species: "Giraffe") // someCreature 的類型是 Animal? 而不是 Animal
    if let giraffe = someCreature {
        print("An animal was initialized with a species of \(giraffe.species)")
    }
    // 打印 "An animal was initialized with a species of Giraffe"
    
    let anonymousCreature = Animal(species: "")
    // anonymousCreature 的類型是 Animal?, 而不是 Animal
    if anonymousCreature == nil {
        print("The anonymous creature could not be initialized")
    }
    // 打印 "The anonymous creature could not be initialized"

重寫一個可失敗構(gòu)造器

    class Document {
        var name: String?
        // 該構(gòu)造器創(chuàng)建了一個 name 屬性的值為 nil 的 document 實例
        init() {}
        // 該構(gòu)造器創(chuàng)建了一個 name 屬性的值為非空字符串的 document 實例
        init?(name: String) {
        self.name = name
        if name.isEmpty { return nil }
    }
}

    class AutomaticallyNamedDocument: Document {
        override init() {
            super.init()
            self.name = "[Untitled]"
        }
        override init(name: String) {
            super.init()
            if name.isEmpty {
                self.name = "[Untitled]"
            } else {
                self.name = name
            }
        }
    }

這個子類重寫了父類的兩個指定構(gòu) 造器,確保了無論是使用 init() 構(gòu)造器,還是使用 init(name:) 構(gòu)造器并為參數(shù)傳遞空字符串,生成的實例中的 name 屬性總有初始 "[Untitled]

必要構(gòu)造器

    //在類的構(gòu)造器前添加 required 修飾符表明所有該類的子類都必須實現(xiàn)該構(gòu)造器:
    class SomeClass {
        required init() {
            // 構(gòu)造器的實現(xiàn)代碼
        }
    }
   // 在重寫父類中必要的指定構(gòu)造器時,不需要添加 override 修飾符:
    class SomeSubclass: SomeClass {
        required init() {
            // 構(gòu)造器的實現(xiàn)代碼
        }
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • 本章將會介紹 存儲屬性的初始賦值自定義構(gòu)造過程默認構(gòu)造器值類型的構(gòu)造器代理類的繼承和構(gòu)造過程可失敗構(gòu)造器必要構(gòu)造器...
    寒橋閱讀 843評論 0 0
  • 構(gòu)造過程是使用類、結(jié)構(gòu)體或枚舉類型的實例之前的準備過程。在新實例可用前必須執(zhí)行這個過程,具體操作包括設置實例中每個...
    莽原奔馬668閱讀 754評論 0 3
  • 構(gòu)造過程 構(gòu)造過程是使用類、結(jié)構(gòu)體或枚舉類型的實例之前的準備過程。在新實例可用前必須執(zhí)行這個過程,具體操作包括設置...
    蠱毒_閱讀 785評論 0 2
  • 文/煎餅 相聚的距離不再親近, 親近的距離不再遙遠, ...
    一直特立獨行的餅閱讀 282評論 0 0
  • 沒有情人的月亮 寫不出浪漫 突兀的念想,涂鴉 一紙凄涼 留白太多的日子,等 玫瑰的馨香
    牛舌掌閱讀 277評論 0 0

友情鏈接更多精彩內(nèi)容