扩展允许我们以一种非常干净的方式修改Swift的数据类型以添加新的功能——我们的新代码与现有代码没有区别。
让我们从一个扩展开始,它将一个扩展添加到一个整数。是的,我意识到的是+=1
,我们从最简单的开始。首先,添加此整数:
var myInt = 0
extension Int
告诉 Swift 我们想为其Int
结构体添加功能。我们也可以使用String
,Array
或者其他的的,但是Int
是一个很好的简单的开始。
使用扩展程序后,其工作方式将变得清晰。将以下行放在扩展名的末尾:
代码语言:javascript复制myInt.plusOne()
在playground上的输出中,您现在将在第一行看到0,在第二行看到1,因此调用plusOne()
返回的数字符合预期。
该扩展名已添加到所有整数,因此您甚至可以这样 调用它:
代码语言:javascript复制5.plusOne()
完成此操作后,您将在输出列中看到 6。
我们的扩展在其输入值上加1并将其返回给调用方,但不修改原始值。尝试输入以下内容:
代码语言:javascript复制var myInt = 10
myInt.plusOne()
myInt
单独使用变量会告诉 playground 仅输出其值,因此在输出列中将看到10,然后是11,然后再次是10。这是原始值,plusOne()
方法的返回值以及原始的未更改值。
为了进一步说明问题,让我们修改plusOne()
方法,使其不返回任何内容,而是修改实例本身(即输入的整数)。
为了实现这一目标,您可能会认为我们需要执行以下操作:
代码语言:javascript复制extension Int {
func plusOne() {
self = 1
}
}
这会删除返回值,因为我们现在不返回任何东西,并且它使用 =
运算符将一个加到self
上。但这是行不通的,实际上Xcode会给您一个令人难以理解的错误消息:“Left side of mutating operator isn't mutable: 'self' is immutable”。
Xcode真正的意思是,默认情况下,Swift不允许您在扩展中修改self
。原因是我们可以使用5.plusOne()
来调用plusOne()
,显然您不能将数字5修改为其他含义。
因此,Swift迫使您使用mutating
声明方法,这意味着它将改变其输入。将扩展名更改为此:
extension Int {
mutating func plusOne() {
self = 1
}
}
现在错误消息将消失。一旦将方法声明为mutating
,Swift就会知道它会更改值,因此它不会让您将其与常量一起使用。例如:
var myInt = 10
myInt.plusOne()
let otherInt = 10
otherInt.plusOne()
第一个整数将被正确修改,但是第二个将失败,因为Swift不允许您修改常量。直接使用数字调用也将报错: "Cannot use mutating member on immutable value: literals are not mutable", 直接使用数字被称为"字面量",报错信息为,字面量不是可变的。
对于开发人员而言,使用扩展为事物添加功能是极为普遍的。在某些方面,扩展与子类相似,那么为什么要使用扩展?
主要原因是可扩展性:扩展适用于所有数据类型,并且当您拥有多个扩展类型时,它们不会冲突。 使用扩展,您可以在十个不同的文件中具有十个不同的功能-它们都可以直接修改同一类型,并且您无需继承任何子类。用于命名扩展文件的常见命名方案是Type Modifier.swift,例如String RandomLetter.swift。
如果您发现自己经常用字符串修剪空格,您可能会厌倦使用这种怪诞的功能:
代码语言:javascript复制str = str.trimmingCharacters(在:.whitespacesAndNewlines中)
…所以为什么不做这样的扩展:
代码语言:javascript复制extension String {
mutating func trim() {
self = trimmingCharacters(in: .whitespacesAndNewlines)
}
}
您可以根据需要扩展任意数量,尽管将不同的功能分隔到单个文件中是一个很好的做法。
本文来自Hacking with Swift 给 swift 初学者的入门课程 Swift for Complete Beginners 的 Extensions