c++构造器可看成与类同名、无返回值的成员函数,而swift构造器用专用的关键字init来标示,语法如下:
init(){
}
与c++一样,swfit构造器也是没有返回值。
struct Celsius {
var temperatureInCelsius: Double
init(fromFahrenheit fahrenheit: Double) {
temperatureInCelsius = (fahrenheit - 32.0) / 1.8
}
init(fromKelvin kelvin: Double) {
temperatureInCelsius = kelvin - 273.15
}
}
默认构造器
类和结构体定义存储属性时有了初始值后,swift提供默认构造器,此外结构体还提供了逐一成员构造器。
struct Size {
var width = 0.0
var height = 0.0
}
let zeroByZero = Size()
let twoByTwo = Size(width: 2.0, height: 2.0)
C++的结构体没有逐一成员构造器。此外,c++也提供了默认构造器,与swift不同,c++对于内置类型(整型、字符型、布尔型、浮点型)不需指定初始值,默认构造器设置为0;对于提供了默认构造器的类型,默认构造器使用该类型的默认构造器初始化该成员变量。
Swift 和c++一样,当显式定义了一个构造器,swift将不提供默认构造器。
指定构造器和便利构造器
与c++不同,swift提供了便利构造器,与便利构造器相对应的称为指定构造器。
convenience init(parameters) {
statements
}
在普通构造器前面加convenience标示便利构造器。
指定构造器和便利构造器的规则:
规则1
指定构造器必须调用其直接父类指定构造器;
规则2
便利构造器必须调用同类的其他构造器;
规则3
便利构造器必须最终导致一个指定构造器被调用。
构造过程
swift和c++的构造过程不同,由于c++是对内存进行操作的,因此其构造过程是先执行基类构造器,后执行子类构造器。
c++构造过程:父类成员初始化列表,父类构造方法内赋值,子类成员初始化列表,子类构造方法内赋值。
swift构造过程包含两个阶段。第一阶段,每个存储属性被引入它们的类指定一个初始值;当每个存储属性的初始值被确定后,第二阶段开始,它给类一次机会,进一步定制它们的存储属性。
swift构造有一个构造链,第一阶段是从下往上,先调用子类的指定构造器,确保子类的所有属性都有值,然后调用父类的指定构造器,并沿着构造链一直往上完成父类的构造过程。
第二阶段,是从上往下,父类的指定的构造器完成调用,子类的指定构造器可以执行更多的定制操作。子类的指定构造器完成调用,便利构造器(如果有的话)可以执行更多的定制操作。
构造器继承与重写
c++构造器不能继承,可以重写;swift构造器可以重写,override是重写关键字。
此外,swift子类满足特定条件,可以自动继承父类构造器。
条件:子类新引入的所有属性都有默认值。符合如下规则:
规则1、如果子类没有定义任何指定构造器,它将自动继承父类的所有指定构造器;
规则2、如果子类提供了所有父类指定构造器的实现(无论是通过规则1获取,或者自定义实现),它将自动继承所有父类的便利构造器。
class Food {
var name: String
init(name: String) {
self.name = name
}
convenience init() {
self.init(name: "[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()
print(oneMysteryItem.name)
print(oneMysteryItem.quantity)
let oneBacon = RecipeIngredient(name: "Bacon")
let sixEggs = RecipeIngredient(name: "Egg", quantity: 6)
class ShoppingListItem: RecipeIngredient {
var purchased = false
var description: String {
var output = "\(quantity) x \(name)"
output += purchased ? " ✔" : " ✘"
return output
}
}
var breakfastList = [
ShoppingListItem(),
ShoppingListItem(name: "Bacon"),
ShoppingListItem(name: "Eggs", quantity: 6),
]
breakfastList[0].name = "Juice"
breakfastList[0].purchased = true
for item in breakfastList {
print(item.description)
}
可失败构造器
在编程实践中,我们会遇到构造失败的情况,c++面对这个情况,如临大敌,需要小心翼翼处理的。swift提供了一个简单的方式—可失败构造器。
在init关键字后面添加问好(?)。
struct Animal {
let species: String
init?(species: String) {
if species.isEmpty { return nil }
self.species = species
}
}