构造器(上)
构造过程是为了使用某个类、结构体或枚举类型的实例而进行的准备过程。这个过程包含了为实例中的每个存储型属性设置初始值和为其执行必要的准备和初始化任务。
构造过程是通过定义构造器(Initializers
)来实现的,这些构造器可以看做是用来创建特定类型实例的特殊方法。与 Objective-C 中的构造器不同,Swift 的构造器无需返回值,它们的主要任务是保证新实例在第一次使用前完成正确的初始化。
类和结构体在实例创建时,必须为所有存储型属性设置合适的初始值。存储型属性的值不能处于一个未知的状态。
你可以在构造器中为存储型属性赋初值,也可以在定义属性时为其设置默认值。以下章节将详细介绍这两种方法。
注意:当你为存储型属性设置默认值或者在构造器中为其赋值时,它们的值是被直接设置的,不会触发任何属性观测器。
init() { // 这是最简单的构造器也是默认构造器 在这个构造器中什么事情都没有做,但是一般会在这里面写一些构造过程 }
struct Fahrenheit { var temperature: Double // 这里没有给定初始值 init() { // temperature是存储属性 在初始化这个实例时必须给定初始值 初始值可以在构造过程中设置 temperature = 32.0 } } // 调用了Fahrenheit的构造器 temperature在构造过程中被设置了 let fahrenheit = Fahrenheit() print(fahrenheit.temperature) // 打印出: 32.0
自定义构造过程
在实际开发中我们经常会自定义构造过程,我们可以为自定义构造器提供参数,为其提供自定义构造所需值的类型和名字。
struct Celsius { var temperatureInCelsius: Double = 0.0 init(fromFahrenheit fahrenheit: Double) { temperatureInCelsius = (fahrenheit - 32.0) / 1.8 } init(fromKelvin kelvin: Double) { temperatureInCelsius = kelvin - 273.15 } // 以上声明了两种构造器,可以根据情况选择任何一种来创建新的实例 } let boilingPointOfWater = Celsius(fromFahrenheit: 212.0) print(boilingPointOfWater.temperatureInCelsius) // 打印出 100.0 let freezingPointOfWater = Celsius(fromKelvin: 273.15) print(freezingPointOfWater.temperatureInCelsius) // 打印出 0.0
注意:如果声明构造器没有指定外部参数名,Swift会生成一个跟内部参数名一样的外部参数名,用以区别不同的构造器
struct Color { var red: Double var yellow: Double var blue: Double init(red: Double, yellow: Double, blue: Double){ self.red = red self.yellow = yellow self.blue = blue } init(white: Double){ red = white yellow = white blue = white } // 如果你不想指定外部参数名,可以用"_" init(_ black: Double){ red = black yellow = black blue = black } } // 在自定义构造器中并没有指定外部参数名,但是Swift还是默认为我们生成了外部参数名 let redColor = Color(red: 1.0, yellow: 0.0, blue: 0.0) let whiteColor = Color(white: 1.0) // 不指定外部参数名 "init(_ black: Double)" let blackColor = Color(0.0)
可选属性类型
如果你定制的类型包含一个逻辑上允许取值为空的存储型属性--不管是因为它无法在初始化时赋值,还是因为它可以在之后某个时间点可以赋值为空--你都需要将它定义为可选类型。可选类型的属性将自动初始化为空nil
,表示这个属性是故意在初始化时设置为空的。
class SurveyQuestion{ var text: String var response: String? init(text: String){ self.text = text // response是可空类型,所以就算没有指定默认值 构造过程中也没有设置它的值也不会报错,但是它会默认设置为空(nil) } }
构造过程中设置常量属性
只要在构造过程结束前常量的值能确定,你可以在构造过程中的任意时间点修改常量属性的值。
注意:对某个类实例来说,它的常量属性只能在定义它的类的构造过程中修改;不能在子类中修改。
class SurveyQuestion{ let text: String var response: String? init(text: String){ // text是常量 只要text在声明时没有指定默认值,那么在构造过程中可以有一次机会来设置它的值 self.text = text } }
结构体的逐一构造器
如果结构体对所有存储型属性提供了默认值且自身没有提供定制的构造器,它们能自动获得一个逐一成员构造器。
struct Size { var width = 0.0 var height = 0.0 } // 逐一构造器 let size = Size( 11.0, height: 5.0)