• Swift 中的Getter 和 Setter


    目录

    前言

    1. 什么是Getter和Setter

    1.定义

    2.作用

    2.属性

    1.存储属性

    2.计算属性

    3.属性观察者

    3. 使用 Getter 和 Setter 的场景

    1.数据转换

    2.懒加载

    3.数据验证和限制

    4.触发相关操作

    4.自定义Getter 和 Setter

    5. 参考资料


    前言

            属性是 Swift 编程中的基本组成部分,它们在类、结构体和枚举中存储和管理数据。属性可以分为存储属性、计算属性和属性观察者,每种属性都有其特定的用途和重要性。

            在 Swift 编程中,属性是存储和管理数据的关键组件。属性可以分为存储属性和计算属性。在处理计算属性时,我们经常会使用到 getter 和 setter,这两个概念对于控制属性的读取和写入行为非常重要。

            这篇博客主要介绍下Swift中的属性和settter和getter方法

    1. 什么是Getter和Setter

    1.定义

            Getter和Setter是访问属性值的两种方法。它们主要用于计算属性,通过这两种方法,我们可以在读取或设置属性值时执行特定的逻辑。

    1. Getter:用来获取属性的值。
    2. Settter:用来设置属性的值。

    2.作用

            GetterSetter 是访问属性值的两种方法。它们主要用于计算属性,通过这两种方法,我们可以在读取或设置属性值时执行特定的逻辑。

    1. 数据验证和清理:在 setter 中可以添加数据验证逻辑,确保属性值符合预期。在 getter 中可以进行数据格式化或其他处理。
    2. 延迟计算:在 getter 中可以进行延迟计算,只在需要时才计算属性值,从而节省资源。
    3. 触发相关行为:在 setter 中可以触发其他属性的更新或执行其他副作用,比如通知观察者属性值的变化。
    4. 封装复杂逻辑:通过 getter 和 setter,可以将复杂的计算或逻辑封装在属性中,保持代码的简洁和可读性。

    2.属性

            在Swift中,属性可以分为存储属性和计算属性。存储属性是类或者结构体的一部分,用来存储常来那个或者变量的值。它们是最基本的属性类型,直接存储在对象的内存中。

    1.存储属性

            存储属性的类型

            1.常量存储属性(let):定义后不能改变,只能初始化的时候设置值。

            2.变量存储属性(var):定义后值可以改变。

            我们可以通过下面的代码看一下存储属性的用法:

    1. struct Person {
    2. let firstName: String // 常量存储属性
    3. var lastName: String // 变量存储属性
    4. }
    5. var person = Person(firstName: "John", lastName: "Doe")
    6. print("Full Name: \(person.firstName) \(person.lastName)") // 输出: Full Name: John Doe
    7. // 修改 lastName 的值
    8. person.lastName = "Smith"
    9. print("Full Name: \(person.firstName) \(person.lastName)") // 输出: Full Name: John Smith
    10. // 尝试修改 firstName 的值(会产生编译错误)
    11. // person.firstName = "Jane"

            在这个例子中,firstName 是一个常量存储属性,一旦赋值就不能改变。而 lastName 是一个变量存储属性,可以随时修改。

           我们还可以使用lazy关键字来延迟存储属性。

    1. class DataManager {
    2. var data = [String]()
    3. init() {
    4. print("DataManager初始化.")
    5. }
    6. }
    7. class ViewController {
    8. lazy var dataManager = DataManager() // 延迟存储属性
    9. init() {
    10. print("ViewController初始化.")
    11. }
    12. }
    13. let viewController = ViewController()
    14. print("Accessing dataManager...")
    15. viewController.dataManager.data.append("Sample Data")
    16. print("DataManager data: \(viewController.dataManager.data)")

            控制台输出结果如下:

            我们可以看到,dataManager属性在首次访问的时候才被初始化,这样可以避免在ViewController初始化的时候进行不必要的开销。

            可选类型的属性允许为空,可以使用?来定义可选类型的存储属性。

    1. struct Car {
    2. var model: String
    3. var owner: String?
    4. }

            在下面的代码中,Car的owner属性就是可选的。

    2.计算属性

            在 Swift 中,计算属性(Computed Properties)是类、结构体或枚举的一部分,它们不直接存储值,而是提供一个 getter 和可选的 setter 来间接获取和设置其他属性或值。计算属性在访问时动态计算其值。

            我们可以使用var定义计算属性,提供一个getter和setter方法。getter用于计算和返回值,setter用来设置值。

             以下面的代码为例,Rectangle的area属性是通过计算来获取的。

    1. struct Rectangle {
    2. var width: Double
    3. var height: Double
    4. var area: Double {
    5. return width * height
    6. }
    7. }
    8. let rect = Rectangle(width: 10.0, height: 5.0)
    9. print("Rectangle Area: \(rect.area)") // 输出: Rectangle Area: 50.0

            上面的代码中,area属性是通过计算来获取的。例子中的area只读的,我们也可以设置既可读也可写的。

            在下面的代码中,我们可以通过设置area获得height,也可以设置width和height获取area属性。

    1. struct Rectangle {
    2. var width: Double
    3. var height: Double
    4. var area: Double {
    5. get {
    6. return width * height
    7. }
    8. set {
    9. height = newValue / width
    10. }
    11. }
    12. }
    13. var rect = Rectangle(width: 10.0, height: 5.0)
    14. print("Rectangle Area: \(rect.area)") // 输出: Rectangle Area: 50.0
    15. rect.area = 100.0
    16. print("New Height: \(rect.height)") // 输出: New Height: 10.0

            我们还可以给枚举类型设置计算属性,下面的例子中,我们定义了两个计算属性inCelsius和inFahrenheit,用于在摄氏度和华氏度之间转换温度。

    1. enum Temperature {
    2. case celsius(Double)
    3. case fahrenheit(Double)
    4. var inCelsius: Double {
    5. switch self {
    6. case .celsius(let value):
    7. return value
    8. case .fahrenheit(let value):
    9. return (value - 32) * 5 / 9
    10. }
    11. }
    12. var inFahrenheit: Double {
    13. switch self {
    14. case .celsius(let value):
    15. return (value * 9 / 5) + 32
    16. case .fahrenheit(let value):
    17. return value
    18. }
    19. }
    20. }
    21. let tempInCelsius = Temperature.celsius(25.0)
    22. print("Temperature in Fahrenheit: \(tempInCelsius.inFahrenheit)") // 输出: Temperature in Fahrenheit: 77.0
    23. let tempInFahrenheit = Temperature.fahrenheit(77.0)
    24. print("Temperature in Celsius: \(tempInFahrenheit.inCelsius)") // 输出: Temperature in Celsius: 25.0

    3.属性观察者

            在 Swift 中,属性观察者(Property Observers)可以监视和响应属性值的变化。无论新值是否与当前值相同,属性观察者都会在属性值改变时调用。你可以为存储属性添加观察者,但不能为计算属性添加观察者。

            观察者属性有两种类型:

    1. willSet:在属性值被存储之前的调用
    2. didSet:在新值被存储之后立即调用

            这两个观察者允许我们在属性值变化前后执行自定义的代码。willSet 会传入新的属性值作为参数,didSet 会传入旧的属性值作为参数:

            例如下面的代码中,我们有一个StepCounter类,它有一个观察者属性couter,默认值为0

    1. class StepCounter {
    2. var counter: Int = 0 {
    3. willSet(counter) {
    4. print("counter willSet 设置为 \(counter)")
    5. }
    6. didSet {
    7. if counter > oldValue {
    8. print("counter didSet \(counter - oldValue) steps")
    9. }
    10. }
    11. }
    12. }

            我们使用下面的代码调用它:

    1. let stepCounter = StepCounter()
    2. stepCounter.counter = 200
    3. stepCounter.counter = 360
    4. stepCounter.counter = 896

            控制台打印信息如下:

            属性观察者是 Swift 中强大的工具,用于监视和响应存储属性值的变化。通过 willSetdidSet,你可以在属性值变化前后执行自定义操作。这对于验证数据、更新 UI 或者实现一些依赖逻辑非常有用。

    3. 使用 Getter 和 Setter 的场景

            上面介绍了属性的类型和getter和setter的用法,我们接下来看一下getter和setter的使用场景

    1.数据转换

    1. class Temperature {
    2. var celsius: Double = 0.0
    3. var fahrenheit: Double {
    4. get {
    5. return celsius * 9 / 5 + 32
    6. }
    7. set {
    8. celsius = (newValue - 32) * 5 / 9
    9. }
    10. }
    11. }
    12. var temp = Temperature()
    13. temp.celsius = 25
    14. print("Celsius: \(temp.celsius)") // Celsius: 25.0
    15. print("Fahrenheit: \(temp.fahrenheit)") // Fahrenheit: 77.0
    16. temp.fahrenheit = 98.6
    17. print("Celsius: \(temp.celsius)") // Celsius: 37.0
    18. print("Fahrenheit: \(temp.fahrenheit)") // Fahrenheit: 98.6

    2.懒加载

            懒加载在iOS开发过程中经常使用,我们ViewController中使用的UI组件都可以使用懒加载的方式去声明。

    1. class DataManager {
    2. lazy var data: [String] = {
    3. // 复杂的初始化逻辑
    4. return ["Data1", "Data2", "Data3"]
    5. }()
    6. }
    7. let manager = DataManager()
    8. // Data will be loaded only when accessed for the first time
    9. print(manager.data) // ["Data1", "Data2", "Data3"]

    3.数据验证和限制

            例如在下面的代码中,我们可以使用set方法对输入的年龄做限制。

    1. class Person {
    2. private var _age: Int = 0
    3. var age: Int {
    4. get {
    5. return _age
    6. }
    7. set {
    8. if newValue >= 0 && newValue <= 120 {
    9. _age = newValue
    10. } else {
    11. print("Invalid age")
    12. }
    13. }
    14. }
    15. }
    16. var person = Person()
    17. person.age = 25
    18. print("Age: \(person.age)") // Age: 25
    19. person.age = -5 // Invalid age
    20. print("Age: \(person.age)") // Age: 25

    4.触发相关操作

            例如在下面的Rectangle中,我们设置好width和height之后,会自动获取area的值。

    1. class Rectangle {
    2. var width: Double = 0.0
    3. var height: Double = 0.0
    4. var area: Double {
    5. get {
    6. return width * height
    7. }
    8. set {
    9. height = newValue / width
    10. }
    11. }
    12. }
    13. var rect = Rectangle()
    14. rect.width = 10
    15. rect.height = 5
    16. print("Area: \(rect.area)") // Area: 50.0
    17. rect.area = 100
    18. print("Height: \(rect.height)") // Height: 10.0

    4.自定义Getter 和 Setter

            更多的时候,我们使用到setter和setter的场景是自定义我们自己的Getter和setter方法,格式如下:

    1. var propertyName: PropertyType {
    2. get {
    3. // 返回计算的值
    4. }
    5. set {
    6. // 执行自定义的设置逻辑
    7. }
    8. }

    5. 参考资料

    1. 官方文档链接
     

  • 相关阅读:
    硕士论文章节划分
    如何在面试中展示跨领域的能力
    算法进阶指南图论 最优贸易
    ASO优化:教你学会如何选词,技巧有哪些?
    软件测试基础学习
    【Typescript基础】类的使用
    日本卫生设备行业协会:日本温水喷淋马桶座出货量达1亿套
    C#异步有多少种实现方式?
    flink-sql所有语法详解-1.16
    6 面向对象
  • 原文地址:https://blog.csdn.net/ZCC361571217/article/details/139292672