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):定义后值可以改变。

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

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

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

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

class DataManager {var data = [String]()init() {print("DataManager初始化.")}
}class ViewController {lazy var dataManager = DataManager() // 延迟存储属性init() {print("ViewController初始化.")}
}let viewController = ViewController()
print("Accessing dataManager...")
viewController.dataManager.data.append("Sample Data")
print("DataManager data: \(viewController.dataManager.data)")

        控制台输出结果如下:

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

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

struct Car {var model: Stringvar owner: String?
}

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

2.计算属性

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

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

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

struct Rectangle {var width: Doublevar height: Doublevar area: Double {return width * height}
}let rect = Rectangle(width: 10.0, height: 5.0)
print("Rectangle Area: \(rect.area)") // 输出: Rectangle Area: 50.0

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

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

struct Rectangle {var width: Doublevar height: Doublevar area: Double {get {return width * height}set {height = newValue / width}}
}var rect = Rectangle(width: 10.0, height: 5.0)
print("Rectangle Area: \(rect.area)") // 输出: Rectangle Area: 50.0rect.area = 100.0
print("New Height: \(rect.height)") // 输出: New Height: 10.0

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

enum Temperature {case celsius(Double)case fahrenheit(Double)var inCelsius: Double {switch self {case .celsius(let value):return valuecase .fahrenheit(let value):return (value - 32) * 5 / 9}}var inFahrenheit: Double {switch self {case .celsius(let value):return (value * 9 / 5) + 32case .fahrenheit(let value):return value}}
}let tempInCelsius = Temperature.celsius(25.0)
print("Temperature in Fahrenheit: \(tempInCelsius.inFahrenheit)") // 输出: Temperature in Fahrenheit: 77.0let tempInFahrenheit = Temperature.fahrenheit(77.0)
print("Temperature in Celsius: \(tempInFahrenheit.inCelsius)") // 输出: Temperature in Celsius: 25.0

3.属性观察者

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

        观察者属性有两种类型:

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

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

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

class StepCounter {var counter: Int = 0 {willSet(counter) {print("counter willSet 设置为 \(counter)")}didSet {if counter > oldValue {print("counter didSet \(counter - oldValue) steps")}}}
}

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

let stepCounter = StepCounter()        
stepCounter.counter = 200        
stepCounter.counter = 360
stepCounter.counter = 896

        控制台打印信息如下:

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

3. 使用 Getter 和 Setter 的场景

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

1.数据转换

class Temperature {var celsius: Double = 0.0var fahrenheit: Double {get {return celsius * 9 / 5 + 32}set {celsius = (newValue - 32) * 5 / 9}}
}var temp = Temperature()
temp.celsius = 25
print("Celsius: \(temp.celsius)") // Celsius: 25.0
print("Fahrenheit: \(temp.fahrenheit)") // Fahrenheit: 77.0temp.fahrenheit = 98.6
print("Celsius: \(temp.celsius)") // Celsius: 37.0
print("Fahrenheit: \(temp.fahrenheit)") // Fahrenheit: 98.6

2.懒加载

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

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

3.数据验证和限制

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

class Person {private var _age: Int = 0var age: Int {get {return _age}set {if newValue >= 0 && newValue <= 120 {_age = newValue} else {print("Invalid age")}}}
}var person = Person()
person.age = 25
print("Age: \(person.age)") // Age: 25person.age = -5 // Invalid age
print("Age: \(person.age)") // Age: 25

4.触发相关操作

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

class Rectangle {var width: Double = 0.0var height: Double = 0.0var area: Double {get {return width * height}set {height = newValue / width}}
}var rect = Rectangle()
rect.width = 10
rect.height = 5
print("Area: \(rect.area)") // Area: 50.0rect.area = 100
print("Height: \(rect.height)") // Height: 10.0

4.自定义Getter 和 Setter

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

var propertyName: PropertyType {get {// 返回计算的值}set {// 执行自定义的设置逻辑}
}

5. 参考资料

1. 官方文档链接
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/19014.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关于 Spring 是什么

Spring 是什么 我们通常所说的 Spring 指的是 Spring Framework&#xff08;Spring 框架&#xff09;&#xff0c;它是⼀个开源框架&#xff0c;有着活跃⽽庞⼤的社区&#xff0c;这就是它之所以能⻓久不衰的原因。Spring ⽀持⼴泛的应⽤场景&#xff0c;它可以让 Java 企业级的…

九章云极DataCanvas公司DingoDB完成中国信通院权威多模数据库测试

2024年5月16日&#xff0c;九章云极DataCanvas公司自主研发和设计的开源多模向量数据库DingoDB顺利完成中国信息通信研究院&#xff08;以下简称中国信通院&#xff09;多模数据库产品测试。本次测试的成功标志着DingoDB在技术能力、性能表现和产品稳定性方面得到了权威机构的高…

python深入探索斐波那契数列:代码示例与不满足的外围条件

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、斐波那契数列的初步实现 二、外围条件的不满足情况 总结 一、斐波那契数列的初步实现 …

存储型XSS

前言 什么是存储型xss&#xff1a; 提交恶意xss数据&#xff0c;存入数据库中&#xff0c;访问时触发。 存储型xss和反射型xss区别&#xff1a; 存储型存入数据库中&#xff0c;可持续时间长&#xff0c;而反射型持续时间短&#xff0c;仅对本次访问有影响&#xff0c;反射型一…

中华活页文选高中版投稿发表

《中华活页文选&#xff08;高中版&#xff09;》创刊于1960年&#xff0c;是中宣部所属中国出版传媒股份有限公司主管、中华书局主办的国家级基础教育期刊&#xff0c;曾获得“中国期刊方阵双效期刊”、国家新闻出版广电总局推荐的“百种优秀报刊”等荣誉称号。本刊以高中学科…

Day 6:2981. 找出出现至少三次的最长特殊子字符串 I

Leetcode 2981. 找出出现至少三次的最长特殊子字符串 I 给你一个仅由小写英文字母组成的字符串 s 。 如果一个字符串仅由单一字符组成&#xff0c;那么它被称为 特殊 字符串。例如&#xff0c;字符串 “abc” 不是特殊字符串&#xff0c;而字符串 “ddd”、“zz” 和 “f” 是特…

性能猛兽:OrangePi Kunpeng Pro评测!

1.引言 随着物联网和嵌入式系统的不断发展&#xff0c;对于性能强大、资源消耗低的单板计算机的需求也日益增加。在这个快节奏的技术时代&#xff0c;单板计算机已成为各种应用场景中不可或缺的组成部分&#xff0c;从家庭娱乐到工业自动化&#xff0c;再到科学研究&#xff0…

差分曼彻斯特编码详解

这是一种双向码&#xff0c;和曼彻斯特编码不同的是&#xff0c;这种码元中间的电平转换边只作为定时信号&#xff0c;不表示数据。数据的表示在于每一位开始处是否有电平转换&#xff1a;有电平转换则表示0&#xff0c;无则表示1。然后这就出现一个问题&#xff0c;很多小伙伴…

App Inventor 2 低功耗蓝牙BLE 两种通信方式:扫描和广播

低功耗蓝牙&#xff0c;也称为蓝牙 LE 或简称 BLE&#xff0c;是一种类似于经典蓝牙的新通信协议&#xff0c;不同之处在于它旨在消耗更少的功耗&#xff0c;同时保持可比的功能。 因此&#xff0c;低功耗蓝牙是与耗电资源有限的物联网设备进行通信的首选。BluetoothLE 扩展需…

DiffBIR论文阅读笔记

这篇是董超老师通讯作者的一篇盲图像修复的论文&#xff0c;目前好像没看到发表在哪个会议期刊&#xff0c;应该是还在投&#xff0c;这个是arxiv版本&#xff0c;代码倒是开源了。本文所指的BIR并不是一个single模型对任何未知图像degradation都能处理&#xff0c;而是用同一个…

数据结构(十)图

文章目录 图的简介图的定义图的结构图的分类无向图有向图带权图&#xff08;Wighted Graph&#xff09; 图的存储邻接矩阵&#xff08;Adjacency Matrix&#xff09;邻接表代码实现 图的遍历深度优先搜索&#xff08;DFS&#xff0c;Depth Fisrt Search&#xff09;遍历抖索过程…

【搜索方法推荐】高效信息检索方法和实用网站推荐

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

同时执行多个python脚本扫描,报如下错误,原因为文件越大读取到内存占用内存越多。

killed nohup python $file unable to fork process cannot allocate memory ls: error while loading shared libraries: libdl.so.2 failed to map segment from shared object cannot allocate memory python进程被系统或者某个用户通过 kill 命令强制终止了

Springboot 实战运用

一&#xff0c;基本配置 1&#xff0c;pom文件配置介绍 1.1继承 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.2</version><relativePath/> <…

ubuntu下载离线软件包及依赖

目录 一、前言 二、正文 1.准备环境 2.开始下载 3.后续工作 三、总结 一、前言 由于给客户提供的设备机不允许上网&#xff0c;那么所有待安装的软件包及依赖库都需要提前下载好&#xff0c;然后通过局域网传过去再安装。 另外&#xff0c;软件包可能还依赖其他的库&…

Mac安装tomcat

代码 brew install tomcat 运行结果如下&#xff1a; 如果要启动输入&#xff1a; brew services start tomcat

新书推荐—华为HCIA路由交换技术实战

新书推荐—华为HCIA路由交换技术实战 由HCIE认证讲师、技术能手、ICT大赛优秀指导教师、教学名师、国家规划教材作者联袂编撰&#xff0c;让学习不再是“硬”茬&#xff0c;而是“嗨”起来&#xff01; 《华为HCIA路由交换技术实战》 作者黄君羡组编正月十六工作室书号978-7-12…

半个月获邀请函|在读博士公派新加坡南洋理工大学联合培养

J同学计划先申报CSC联培博士&#xff0c;如若获批&#xff0c;再走本校的联培资助项目。我们仅用半个月时间&#xff0c;就为其申请到新加坡南洋理工大学&#xff0c;因导师接收名额有限制&#xff0c;其又热心推荐了另一位指导导师&#xff0c;最终J同学如愿获得学校资助出国联…

职校老师的工资待遇怎么样

工资水平一直是教师们关注的焦点&#xff0c;毕竟&#xff0c;工资不仅关系到个人的生活品质&#xff0c;还影响着教师的职业满意度和工作动力。职校教师的工资待遇究竟是怎样的呢&#xff1f; 职校教师的工资水平受多种因素影响&#xff0c;包括地区、学校类型、个人资历和教学…

备份服务器的安全风险以及如何通过TDE透明加密提升安全性

备份服务器的潜在安全风险主要包括以下几个方面&#xff1a; 1. 数据泄露风险&#xff1a; 备份数据可能包含敏感信息&#xff0c;如用户个人信息、商业机密等。如果备份数据未经适当保护&#xff0c;例如存储在不安全的位置或未加密&#xff0c;黑客或未授权的人员可能会获取…