Published 2022-03-10

Swift - 属性

在 Swift 中,属性是一个值或者一组值,它与特定的类、结构体或枚举相关联。属性可以是存储属性或计算属性。

存储属性

存储属性是一种将值存储到实例变量中的属性。存储属性可以是变量属性(用 var 关键字定义)或常量属性(用 let 关键字定义)。

下面是一个存储属性的示例:

struct Rectangle {
  var width = 0.0
  var height = 0.0
}

var rect = Rectangle()
rect.width = 10.0
rect.height = 20.0

print("width: \(rect.width), height: \(rect.height)") // 输出 width: 10.0, height: 20.0

在上面的示例中,我们定义了一个 Rectangle 结构体,它有两个存储属性 width 和 height。然后,我们创建了一个 Rectangle 实例 rect,并将其宽度设置为 10.0,高度设置为 20.0。最后,我们打印出了 rect 实例的宽度和高度。

计算属性

计算属性是一种不直接存储值,而是提供一个 getter 和一个可选的 setter 用于间接获取和设置值的属性。计算属性可以用于计算、转换或验证值。

下面是一个计算属性的示例:

struct Rectangle {
var width = 0.0
var height = 0.0

    var area: Double {
        return width * height
    }
}

var rect = Rectangle()
rect.width = 10.0
rect.height = 20.0

print("area: \(rect.area)") // 输出 area: 200.0

在上面的示例中,我们给 Rectangle 结构体添加了一个计算属性 area,它通过 getter 计算并返回矩形的面积。然后,我们创建了一个 Rectangle 实例 rect,并将其宽度设置为 10.0,高度设置为 20.0。最后,我们打印出了 rect 实例的面积。

属性观察器

属性观察器是一种用于监听属性值变化的属性,它允许在属性值被设置之前或之后执行自定义代码。属性观察器可以应用于存储属性和计算属性。

下面是一个属性观察器的示例:

class StepCounter {
  var totalSteps: Int = 0 {
    willSet(newTotalSteps) {
      print("About to set totalSteps to \(newTotalSteps)")
    }
    didSet {
      if totalSteps > oldValue {
        print("Added \(totalSteps - oldValue) steps")
      }
    }
  }
}

let stepCounter = StepCounter()
stepCounter.totalSteps = 10
stepCounter.totalSteps = 20

在上面的示例中,我们定义了一个 StepCounter 类,它有一个存储属性 totalSteps,并为该属性添加了一个属性观察器。属性观察器包括 willSet 和 didSet 两个方法,分别在属性值被设置之前和之后执行。在 willSet 方法中,我们打印出将要设置的属性值,而在 didSet 方法中,我们比较旧值和新值,并打印出添加的步数。

然后,我们创建了一个 StepCounter 实例 stepCounter,并分别将其 totalSteps 设置为 10 和 20。由于 totalSteps 的值发生了变化,属性观察器被调用,并输出了相关的日志信息。

延迟存储属性

延迟存储属性是一种将属性的初始化推迟到第一次使用该属性时的属性。延迟存储属性使用 lazy 关键字定义。

下面是一个延迟存储属性的示例:

class DataImporter {
  var filename = "data.txt"
  // 模拟数据导入的过程
}

class DataManager {
  lazy var importer = DataImporter()
  var data = [String]()
  // 这里是 DataManager 的其他方法和属性
}

let manager = DataManager()
manager.data.append("Some data")
manager.data.append("Some more data")

// 此时 importer 属性还未被创建
print(manager.importer.filename)

// 第一次访问 importer 属性时,它会被创建

在上面的示例中,我们定义了一个 DataImporter 类,它有一个 filename 存储属性和一个模拟数据导入的方法。然后,我们定义了一个 DataManager 类,它有一个 data 数组属性和一个延迟存储属性 importer。当我们创建一个 DataManager 实例 manager 时,importer 属性不会被创建,直到我们第一次访问它时。在第一次访问 importer 属性时,它会被创建,并执行 DataImporter 的初始化过程。最后,我们打印出了 importer 的 filename 属性。

总之,Swift 的属性提供了一种方便的方式来封装和访问与类、结构体或枚举相关联的值。不同类型的属性具有不同的特点和用途,您可以根据自己的需求选择适合的属性类型。