第十四章 构造过程

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++构造过程:父类成员初始化列表,父类构造方法内赋值,子类成员初始化列表,子类构造方法内赋值。

第十四章 构造过程_第1张图片

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

    }

}

你可能感兴趣的:(第十四章 构造过程)