Swift 中 extension 的使用
在 Swift 中,extension
是一种非常有用的语言特性,它可以为一个已有的类型(包括类、结构体和枚举)添加新的属性、方法、下标和协议等功能,而无需修改原始类型的定义。使用 extension
可以让我们更加方便地扩展和修改现有的代码,同时也可以使代码更加清晰和易读。
下面是一些 extension
的使用示例:
1. 为类型添加新的方法
extension Int {
func times(_ closure: () -> Void) {
for _ in 0..<self {
closure()
}
}
}
3.times { print("Hello") } // 输出三次 "Hello"
在上面的代码中,我们为 Int
类型添加了一个名为 times
的方法,这个方法接受一个闭包作为参数,并在闭包中执行指定次数的操作。在调用时,我们可以使用 3.times { print("Hello") }
的语法来输出三次 "Hello"。
2. 为类型添加新的计算属性
extension Double {
var squared: Double {
return self * self
}
}
let x = 3.0
let y = x.squared // y 的值为 9.0
在上面的代码中,我们为 Double
类型添加了一个名为 squared
的计算属性,这个属性返回当前值的平方。在调用时,我们可以使用 x.squared
的语法来计算 x
的平方并将结果赋值给 y
。
3. 为类型添加新的下标
extension Array {
subscript(safe index: Int) -> Element? {
return indices.contains(index) ? self[index] : nil
}
}
let array = [1, 2, 3]
let element = array[safe: 10] // element 的值为 nil
在上面的代码中,我们为 Array
类型添加了一个名为 safe
的下标,这个下标接受一个整数作为参数,并返回数组中对应索引位置的元素(如果该索引位置存在的话),否则返回 nil
。在调用时,我们可以使用 array[safe: 10]
的语法来获取数组中索引为 10 的元素,由于该索引位置不存在,因此返回值为 nil
。
4. 为类型遵循新的协议
protocol Runnable {
func run()
}
extension UIViewController: Runnable {
func run() {
print("ViewController is running")
}
}
let viewController = UIViewController()
viewController.run() // 输出 "ViewController is running"
在上面的代码中,我们为 UIViewController
类型遵循了一个名为 Runnable
的协议,并为该类型添加了一个 run
方法。在调用时,我们可以使用 viewController.run()
的语法来执行 ViewController
中的 run
方法,并输出 "ViewController is running"。
总之,extension
是一种非常有用的语言特性,可以让我们更加灵活地扩展和修改现有的代码,从而提高开发效率和代码质量。
问题:你能通过extension(扩展)保存一个属性吗?请解释一下原因。
在 Swift 中,我们可以使用 extension
来为一个已有的类型添加新的属性和方法。但是,我们不能使用 extension
来添加存储属性,因为存储属性必须在类型的定义中进行声明。
因为 extension
是在类型的定义之外添加新的功能,它只能添加计算属性,也就是只有 getter 和 setter 方法的属性,而没有实际的存储空间来存储属性值。因此,如果我们在 extension
中尝试添加一个存储属性,编译器会提示错误。
下面是一个示例代码:
struct Person {
var name: String
}
extension Person {
var age: Int // 编译错误:Extensions must not contain stored properties
}
在上面的代码中,我们尝试在 Person
结构体的 extension
中添加一个 age
属性,但是编译器会提示错误,因为我们不能在 extension
中添加存储属性。
不过,我们可以在 extension
中添加计算属性,这些属性会在每次访问时计算出一个值,如下所示:
extension Person {
var fullName: String {
return "(name)"
}
}
在上面的代码中,我们在 Person
结构体的 extension
中添加了一个 fullName
计算属性,这个属性只有 getter 方法,每次访问时都会计算出一个完整的姓名并返回。
相关文章
- 一周趣评:个人信息保护法实施;脸书关闭人脸识别系统
- 第1节:感知机perceptron原理与numpy复现
- 戴尔分拆价值640亿美元的VMware以减轻债务负担
- [Python从零到壹] 十一.数据分析之Numpy、Pandas、Matplotlib和Sklearn入门知识万字详解
- 算力≠智慧!MIT教授「意识来源」新理论:人类认知与计算没关系
- 【小知识】使用串口8bit,7bit和6bit数据格式的奇偶校验问题
- 【STM32H7教程】第93章 STM32H7的SPI总线应用之驱动ADS1256(8通道24bit ADC, 增益可编程)
- 模型泛化不必随机训练全批量GD媲美SGD,网友:计算成本负担不起
- 比超级计算机快亿亿亿倍!中科大成功研制113个光子的“九章二号”量子计算机原型
- 比超级计算机快千万倍 我国量子计算研究获重要进展
- 中国如何赢得新一轮超算竞赛?关键在向数据密集型超算转变
- 400倍加速,PolarDB HTAP实时数据分析技术解密
- 台积电被逼服软!11月8日前将提交所有机密数据
- 阿里OceanBase GitHub点赞送礼引争议,CTO道歉,贾扬清、李沐讨论
- 黑客把你家网线作“天线”,读取电磁信号就能偷走数据
- 云安全漏洞事件频发,我们能从中学到什么?
- 为什么微服务要有独立数据库
- 中科院院士郭光灿:“要把中国量子计算机卖到国外”
- 谷歌云押注多云和边缘计算:追赶亚马逊和微软
- 性能优化系列:每个程序员都应该知道的数字