Swift 构造函数(Initializer)

在本教程中,我们将通过实例了解 Swift 构造函数(Initializer)及其类型。

Initializer 是一种特殊类型的函数,用于创建类或结构的对象。

在 Swift 中,我们使用 init() 方法创建构造函数(Initializer)。例如,

  1. class Wall {
  2. ...
  3. // create an initializer
  4. init() {
  5. // perform initialization
  6. ...
  7. }
  8. }

这里,方法 init() 是类 Wall 的构造函数。

实例:初始化
  1. // declare a class
  2. class Wall {
  3. var length: Double
  4. // initializer to initialize property
  5. init() {
  6. length = 5.5
  7. print("Creating a wall.")
  8. print("Length = ", length)
  9. }
  10. }
  11. // create an object
  12. var wall1 = Wall()

结果如下:

  1. Creating a wall.
  2. Length = 5.5

在上面的实例中,我们创建了一个名为 init() 的构造函数。在构造函数中,我们已经初始化了 length 属性的值。

请注意以下语句:

  1. // create an object
  2. var wall1 = Wall()

这里,当创建 wall1 对象时,将调用 init() 构造函数。并且,length 属性的值初始化为 5.5


参数化初始化

Swift 构造函数也可以接受一个或多个参数。这种初始化称为参数化初始化(带参数的初始化)。

让我们看一个例子,

  1. class Wall {
  2. var length: Double
  3. ...
  4. // initializer with parameter
  5. init(length: Double) {
  6. self.length = length
  7. }
  8. }
  9. // create an object
  10. var wall1 = Wall(length: 10.5)

这里,

init(length: Double) - 设定参数长度的初始化

var wall1 = Wall(length: 10.5) - 将值 10.5 传递给参数 length

self.length = lengthlength 长度参数 (10.5) 的值赋值给 length 属性

self.length - 指定 length 属性与当前对象 wall1 关联

实例:参数化初始化
  1. // declare a class
  2. class Wall {
  3. var length: Double
  4. var height: Double
  5. // parameterized initializer to initialize properties
  6. init(length: Double, height: Double) {
  7. self.length = length
  8. self.height = height
  9. }
  10. func calculateArea() -> Double {
  11. return length * height
  12. }
  13. }
  14. // create object and initialize data members
  15. var wall1 = Wall(length: 10.5, height: 8.6)
  16. var wall2 = Wall(length: 8.5, height: 6.3)
  17. print("Area of Wall 1: ", wall1.calculateArea())
  18. print("Area of Wall 2: ", wall2.calculateArea())

结果如下:

  1. Area of Wall 1: 90.3
  2. Area of Wall 2: 53.55

在上面的实例中,我们创建了一个初始化程序 init(),其中包含两个参数:lengthheight。请注意这些表达式,

  1. var wall1 = Wall(length: 10.5, height: 8.6)
  2. var wall2 = Wall(length: 8.5, height: 6.3)

在这里,在创建 Wall 类的对象时,我们将成员属性的值作为参数传递。

通过初始化成员变量,我们现在可以使用 calculateArea() 方法计算墙的面积。


初始化重载

Swift 初始化可以以与 函数重载 类似的方式重载。

在初始化程序重载中,如果两个或多个初始化程序具有不同类型或数量的参数,则它们可以具有相同的名称。

并且,根据对象创建期间传递的参数,调用相应的初始化构造函数。

让我们看一个例子,

  1. class Person {
  2. var age: Int
  3. // 1. initializer with no arguments
  4. init() {
  5. age = 20
  6. }
  7. // 2. initializer with an argument
  8. init(age: Int) {
  9. self.age = age
  10. }
  11. // method to return age
  12. func getAge() -> Int {
  13. return age
  14. }
  15. }
  16. var person1 = Person()
  17. var person2 = Person(age: 23)
  18. print("Person1 Age:", person1.getAge())
  19. print("Person1 Age:", person2.getAge())

结果如下:

  1. Person1 Age: 20
  2. Person1 Age: 23

在上面的实例中,我们创建了一个类 Person,它具有单个属性 age

我们还定义了两个构造函数:init()init(age:Int)

我们没有向 person1 对象传递任何参数,因此调用了第一个构造函数。因此,age 被初始化为 20

我们已经将 23 作为参数传递给 person2。因此,第二个构造函数被调用,age 被初始化为 23

方法 getAge() 返回 age 的值,我们使用它来打印 person1person2 的年龄。


Swift 便捷初始化

在前面的实例中,我们定义的初始化构造函数类的主初始值。这些主要初始化也称为指定初始化。

然而,我们也可以为一个名为便利初始化的类定义一个辅助/支持初始化的构造函数。

为了定义便捷初始化函数,我们在初始化之前使用关键字 convenience。例如,

  1. class University {
  2. var name : String
  3. var rank : String
  4. init(name : String, rank: String) {
  5. self.name = name
  6. self.rank = rank
  7. }
  8. // define convenience init
  9. convenience init() {
  10. self.init(name: "Kathmandu University", rank: "1st")
  11. }
  12. }
  13. var university1 = University()
  14. print(university1.name)
  15. print("Rank:", university1.rank)

结果为:

  1. Kathmandu University
  2. Rank: 1st

在上面的实例中,我们创建了一个指定的初始化:init() 和一个便捷初始化:convenience init()

在便捷初始化中,我们调用了指定的初始化函数并为属性赋值。

  1. convenience init() {
  2. self.init(name: "Kathmandu University", rank: "1st")
  3. }

创建 university1 对象时,将调用便捷初始化。

  1. // using convenience initializer
  2. var university1 = University()

与调用指定的初始化程序相比,这使我们的代码看起来更简洁:

  1. // call designated initializer
  2. var university1 = University(name: "Kathmandu University", rank: "1st")
注意:在为存储的属性指定默认值时,便捷初始化非常有用。

失败的初始化

在某些情况下,初始化构造函数可能正常运行,也可能不运行,这称为失败的初始化。

我们通过放置一个问号(?)来编写一个失败的初始值设定项在 init 关键字之后,如果出现错误,则返回 nil。例如,

  1. class File {
  2. var folder: String
  3. // failable initializer
  4. init?(folder: String) {
  5. // check if empty
  6. if folder.isEmpty {
  7. print("Folder Not Found") // 1st output
  8. return nil
  9. }
  10. self.folder = folder
  11. }
  12. }
  13. // create folder1 object
  14. var file = File(folder: "")
  15. if (file != nil) {
  16. print("File Found Successfully")
  17. }
  18. else {
  19. print("Error Finding File") // 2nd output
  20. }

结果如下:

  1. Folder Not Found
  2. Error Finding File

在上面的例子中,我们已经创建了失败的初始化程序 init?(),参数名为 folder

并且,我们使用了 if 语句和 isEmpty 属性

  1. if (folder.isEmpty) { return nil }

检查文件夹是否为空,如果为空则返回 nil

对于 folder1 对象,我们传递了一个空字符串 "",它会触发初始化失败,因此首先执行其中的语句,然后返回 nil

最后,执行 else 块内的语句。


结构成员初始化

在 Swif t中,我们不需要在使用结构时创建初始值设定项。Swift 会自动为我们生成一个成员。例如,

  1. struct Person {
  2. var name: String
  3. var age: Int
  4. }

这里,我们没有在 Person 结构中创建任何初始值设定项。然而,Swift 会自动为我们生成一个成员初始化,

  1. var person1 = Person(name: "Dwight", age: 43)

在这里,括号 () 内的值自动赋值给结构的相应属性。这称为成员初始化。

实例:成员初始化
  1. struct Person {
  2. // define two properties
  3. var name: String
  4. var age: Int
  5. }
  6. // object of Person with memberwise initializer
  7. var person1 = Person(name: "Dwight", age: 43)
  8. print("Name:", person1.name)
  9. print("Age:", person1.age)

结果为:

  1. Name: Dwight
  2. Age: 43

在上面的实例中,我们使用了自动生成的成员初始值来为 Person 结构的相应属性赋值。

  1. var person1 = Person(name: "Dwight", age: 43)

这里,name 的值设置为 Dwightage 设置为 43