Swift 类与结构体[初始化器]

作者: iOS雯Ping | 来源:发表于2019-01-07 18:35 被阅读44次

初始化 (Initialization)

Initialization是为准备使用类,结构体或者枚举实例的一个过程。这个过程涉及了在实例里的每一个存储属性设置一个初始值,以及在新实例准备使用之前执行任何其他所必须的设置或初始化。
你通过定义初始化器实现这次初始化过程,这是一个特殊的方法可以被调用来创建一个新的实例。不向Objective-C的初始化器,Swift初始化器没有返回值。这些初始化器主要的角色就是确保在第一次使用的时候,能过正确的创建一个新的实例。

设置存储属性的初始值 (Setting Inital Values for Stored Properties)

在一个类或结构体的实例被创建的时候,类和结构体必须为所有的存储属性设置一个合适的初始值。存储属性不能放在不确定的状态中。
注意:当设置存储属性的默认值或者在初始化器内设置初始值时,是直接把值设置给属性,不会调用属性观察者。

初始化器 (Initializers)

使用init关键字定义一个初始化器:

init() {
    // perform some initialization here
}

下面的定义了一个名为Fahrenheit结构体,存储以华氏刻度(Fahrenheit scale)表示的温度。Fahrenheit结构体有一个Double类型的存储属性temperature:

struct Fahrenheit { 
var temperature: Double init() { temperature = 32.0
 } 
       } 
var f = Fahrenheit()
 print("The default temperature \(f.temperature)° Fahrenheit") 
//prints "The default temperature is 32.0° Fahrenheit"

默认的属性值

struct Fahrenheit {
    var temperature = 32.0
}

自定义初始化

你可以通过输入形式参数和可选(optional)类型自定义初始化过程,或者在初始化的时候分配常量属性,下面的部分将会描述。

初始化参数 (Initialization Parameters)

在定义初始化器时,可以提供一些初始化参数。下面这个例子提供了两个初始化器:

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 is 100.0
let freezingPointOfWater = Celsius(fromKelvin: 273.15)
// freezingPointOfWater.temperatureInCelsius is 0.0

参数名和参数标签 (Parameter Names and Argumenet Labels)

你可以提供初始化形式参数作为初始化器的一部分,来自定义初始化器中值的类型和名字。初始化形式参数有相同的功能和语法作为函数和方法的形式参数。
例如下面这个例子,提供了两个初始化器:

struct Color {
    let red, green, blue: Doublev
init(red: Double, green: Double, blue: Double) {
        self.red   = red
 self.green = green
        self.blue  = blue
 }
    init(white: Double) {
        red   = white
 green = white
        blue  = white
    }
}

let magenta = Color(red: 1.0, green: 0.0, blue: 1.0)
let halfGray = Color(white: 0.5)

注意:在调用上面的初始化器时不能不使用参数标签,如果把参数标签删掉,会报编译错误:

let veryGreen = Color(0.0, 1.0, 0.0)
// this reports a compile-time error - argument labels are required

初始化器形式参数不用外部名称

如果你不想为初始化器形式参数使用外部名称,可以写一个下划线(_)为那个形式参数替代明确的外部名称,从而可以重写默认的行为。
这里有一个扩大的Celsius类的,有一个额外的初始化器来创建一个新的Celsius类实例:

struct Celsius {
    var temperatureInCelsius:Double
init(fromFahrengeit fahrenheit: Double) {
        temperatureInCelsius = (fahrenheit - 32.0) / 1.8
 }
    init(fromKevlvin kelvin: Double) {
        temperatureInCelsius = kelvin - 273.15
}
    init(_ celsius: Double) {
        temperatureInCelsius = celsius
    }
}
let bodyTemperature = Celsius(37.0)
// bodyTemperature.temperatureInCelsius is 37.0

初始化器调用Celsius(37.0)有着清楚的意图,而不需要一个外部形式参数名。因此,适当地写初始化器为init(_ celsius: Double),那样,它就可以通过一个无名的Double值被调用了。

可选属性类型 (Optional Property Types)

在自定义一个类时,某些存储属性可能没有值,也许是因为在初始化时还不能设置属性的值,或者是后续可以没有值,那么这个属性应该定义为可选类型。在初始化时,可选类型的属性的值是nil
例如:

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?")
cheeseQuestion.ask()
// Prints "Do you like cheese?"
cheeseQuestion.response = "Yes, I do like cheese."

Swift 类与结构体[初始化器]

你可以在初始化器里为存储属性设置初始值。另外,指定一个默认属性值作为属性的声明。当属性被定义的时候,你可以通过为这个属性分配一个初始值来指定默认的属性值。

class Vehicle {
    var numberOfWheels = 0 // 为存储属性提供了默认值 0
    var description:String {
        return "\(numberOfWheels) wheel(s)"
    }
}

let vehicle = Vehicle()
//print("vehicle: \(vehicle.description)")

class Bicycle:Vehicle {
    override init() {
        super.init()
        numberOfWheels = 2
    }
}

// super.init() 这句话的作用: 调用父类的初始化器. 可以确保Bicycle在修改属性之前他所继承的属性 numberOfWheels 能被 vehicle 类初始化. 在调用 super.init()之后,一开始的numberOfWheels值被新值 2 替换.
let vehicle2 = Bicycle()
//print("\(vehicle2.description)")


// 指定和便捷初始化器实战
class Food {
    var name:String     // 存储属性: name
    
    init(name:String) { // 这里没有调用super.init()是因为Food类,没有父类
        self.name = name
    }
    
    convenience init(){
        self.init(name: "[Unnamed]")
    }
}

let nameMeat = Food(name: "Bacon")
//print(nameMeat.name) -> Bacon

let mysteryMeat = Food()
//print(mysteryMeat.name) -> [Unnamed]

// 类初始化必须保证每个成员变量都有初始值: [参考文] 在创建类和结构体的实例时必须为所有的存储属性设置一个合适的初始值
//如果没有init 指定初始化器 , 就必须给存储变量一个默认初始化值
//var name:String = "" 存储属性 name 默认给一个空字符串

// 初始化器中分配常量属性
class SurveyQuestion {
    let text : String
    var response:String?
    init(text:String) {
        self.text = text
    }
    func ask(){
        print(text)
    }
}

let beetsQuestion = SurveyQuestion(text: "How about beets?" )
//beetsQuestion.ask() // How about beets?
beetsQuestion.response = "I also like beets. (But not with cheese.)"



// 默认初始化器
//Swift 为所有没有提供初始化器的结构体或类提供了一个默认的初始化器来给所有的属性提供了默认值.这个默认的初始化器只是将当地创建了一个所有属性都有默认值的新实例.
class ShoppingListItem{
    var name:String?
    var quantity = 1
    var purchased = false
}

var item = ShoppingListItem()
//print(item.name,item.quantity,item.purchased) -> nil 1 false

晓雯给大家推荐一个iOS技术交流群:691040931群内提供数据结构与算法、底层进阶、swift、逆向、底层面试题整合文档等免费资料!!!
需要更多的iOS资料记得联系晓雯!!!晓雯微信:Pingwen20

相关文章

网友评论

    本文标题:Swift 类与结构体[初始化器]

    本文链接:https://www.haomeiwen.com/subject/frhprqtx.html