Swift 构造过程
构造过程是为了使用某个类、结构体或枚举类型的实例而进行的准备过程。这个过程包含了为实例中的每个属性设置初始值和为其执行必要的准备和初始化任务。
Swift 构造函数使用 init() 方法。
与 Objective-C 中的构造器不同,Swift 的构造器无需返回值,它们的主要任务是保证新实例在第一次使用前完成正确的初始化。
类实例也可以通过定义析构器(deinitializer)在类实例释放之前执行清理内存的工作。
存储型属性的初始赋值
类和结构体在实例创建时,必须为所有存储型属性设置合适的初始值。
存储属性在构造器中赋值时,它们的值是被直接设置的,不会触发任何属性观测器。
存储属性在构造器中赋值流程:
创建初始值。
在属性定义中指定默认属性值。
初始化实例,并调用 init() 方法。
构造器
构造器在创建某特定类型的新实例时调用。它的最简形式类似于一个不带任何参数的实例方法,以关键字init命名。
语法
init() { // 实例化后执行的代码 }
实例
以下结构体定义了一个不带参数的构造器 init,并在里面将存储型属性 length 和 breadth 的值初始化为 6 和 12:
struct rectangle { var length: Double var breadth: Double init() { length = 6 breadth = 12 } } var area = rectangle() print("矩形面积为 \(area.length*area.breadth)")
以上程序执行输出结果为:
矩形面积为 72.0
默认属性值
我们可以在构造器中为存储型属性设置初始值;同样,也可以在属性声明时为其设置默认值。
使用默认值能让你的构造器更简洁、更清晰,且能通过默认值自动推导出属性的类型。
以下实例我们在属性声明时为其设置默认值:
struct rectangle { // 设置默认值 var length = 6 var breadth = 12 } var area = rectangle() print("矩形的面积为 \(area.length*area.breadth)")
以上程序执行输出结果为:
矩形面积为 72
构造参数
你可以在定义构造器 init() 时提供构造参数,如下所示:
struct Rectangle { var length: Double var breadth: Double var area: Double init(fromLength length: Double, fromBreadth breadth: Double) { self.length = length self.breadth = breadth area = length * breadth } init(fromLeng leng: Double, fromBread bread: Double) { self.length = leng self.breadth = bread area = leng * bread } } let ar = Rectangle(fromLength: 6, fromBreadth: 12) print("面积为: \(ar.area)") let are = Rectangle(fromLeng: 36, fromBread: 12) print("面积为: \(are.area)")
以上程序执行输出结果为:
面积为: 72.0 面积为: 432.0
内部和外部参数名
跟函数和方法参数相同,构造参数也存在一个在构造器内部使用的参数名字和一个在调用构造器时使用的外部参数名字。
然而,构造器并不像函数和方法那样在括号前有一个可辨别的名字。所以在调用构造器时,主要通过构造器中的参数名和类型来确定需要调用的构造器。
如果你在定义构造器时没有提供参数的外部名字,Swift 会为每个构造器的参数自动生成一个跟内部名字相同的外部名。
struct Color { let red, green, blue: Double 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 } } // 创建一个新的Color实例,通过三种颜色的外部参数名来传值,并调用构造器 let magenta = Color(red: 1.0, green: 0.0, blue: 1.0) print("red 值为: \(magenta.red)") print("green 值为: \(magenta.green)") print("blue 值为: \(magenta.blue)") // 创建一个新的Color实例,通过三种颜色的外部参数名来传值,并调用构造器 let halfGray = Color(white: 0.5) print("red 值为: \(halfGray.red)") print("green 值为: \(halfGray.green)") print("blue 值为: \(halfGray.blue)")
以上程序执行输出结果为:
red 值为: 1.0 green 值为: 0.0 blue 值为: 1.0 red 值为: 0.5 green 值为: 0.5 blue 值为: 0.5
没有外部名称参数
如果你不希望为构造器的某个参数提供外部名字,你可以使用下划线_
来显示描述它的外部名。
struct Rectangle { var length: Double init(frombreadth breadth: Double) { length = breadth * 10 } init(frombre bre: Double) { length = bre * 30 } //不提供外部名字 init(_ area: Double) { length = area } } // 调用不提供外部名字 let rectarea = Rectangle(180.0) print("面积为: \(rectarea.length)") // 调用不提供外部名字 let rearea = Rectangle(370.0) print("面积为: \(rearea.length)") // 调用不提供外部名字 let recarea = Rectangle(110.0) print("面积为: \(recarea.length)")
以上程序执行输出结果为:
面积为: 180.0 面积为: 370.0 面积为: 110.0
可选属性类型
如果你定制的类型包含一个逻辑上允许取值为空的存储型属性,你都需要将它定义为可选类型optional type(可选属性类型)。
当存储属性声明为可选时,将自动初始化为空 nil。
struct Rectangle { var length: Double? init(frombreadth breadth: Double) { length = breadth * 10 } init(frombre bre: Double) { length = bre * 30 } init(_ area: Double) { length = area } } let rectarea = Rectangle(180.0) print("面积为:\(rectarea.length)") let rearea = Rectangle(370.0) print("面积为:\(rearea.length)") let recarea = Rectangle(110.0) print("面积为:\(recarea.length)")
以上程序执行输出结果为:
面积为:Optional(180.0) 面积为:Optional(370.0) 面积为:Optional(110.0)
构造过程中修改常量属性
只要在构造过程结束前常量的值能确定,你可以在构造过程中的任意时间点修改常量属性的值。
对某个类实例来说,它的常量属性只能在定义它的类的构造过程中修改;不能在子类中修改。
尽管 length 属性现在是常量,我们仍然可以在其类的构造器中设置它的值:
struct Rectangle { let length: Double? init(frombreadth breadth: Double) { length = breadth * 10 } init(frombre bre: Double) { length = bre * 30 } init(_ area: Double) { length = area } } let rectarea = Rectangle(180.0) print("面积为:\(rectarea.length)") let rearea = Rectangle(370.0) print("面积为:\(rearea.length)") let recarea = Rectangle(110.0) print("面积为:\(recarea.length)")
以上程序执行输出结果为:
面积为:Optional(180.0) 面积为:Optional(370.0) 面积为:Optional(110.0)
默认构造器
默认构造器将简单的创建一个所有属性值都设置为默认值的实例:
以下实例中,ShoppingListItem类中的所有属性都有默认值,且它是没有父类的基类,它将自动获得一个可以为所有属性设置默认值的默认构造器
class ShoppingListItem { var name: String? var quantity = 1 var purchased = false } var item = ShoppingListItem() print("名字为: \(item.name)") print("数理为: \(item.quantity)") print("是否付款: \(item.purchased)")
以上程序执行输出结果为:
名字为: nil 数理为: 1 是否付款: false
结构体的逐一成员构造器
如果结构体对所有存储型属性提供了默认值且自身没有提供定制的构造器,它们能自动获得一个逐一成员构造器。
我们在调用逐一成员构造器时,通过与成员属性名相同的参数名进行传值来完成对成员属性的初始赋值。
下面例子中定义了一个结构体 Rectangle,它包含两个属性 length 和 breadth。Swift 可以根据这两个属性的初始赋值100.0 、200.0自动推导出它们的类型Double。
struct Rectangle { var length = 100.0, breadth = 200.0 } let area = Rectangle(length: 24.0, breadth: 32.0) print("矩形的面积: \(area.length)") print("矩形的面积: \(area.breadth)")
由于这两个存储型属性都有默认值,结构体 Rectangle 自动获得了一个逐一成员构造器 init(width:height:)。 你可以用它来为 Rectangle 创建新的实例。
以上程序执行输出结果为:
名字为: nil 矩形的