扩展
就是为一个已有的类、结构体、枚举类型或者协议类型添加新功能,但是不能重写已有的功能。
Swift
中的扩展可以:
- 添加计算型属性和计算型类型属性
- 定义实例方法和类型方法
- 提供新的构造器
- 定义下标
- 定义和使用新的嵌套类型
- 使一个已有类型符合某个协议
扩展语法
使用关键字extension
来声明扩展:
extension SomeType {
// 为 SomeType 添加的新功能写到这里
}
可以通过扩展来扩展一个已有类型,使其采纳一个或多个协议。在这种情况下,无论是类还是结构体,协议名字的书写方式完全一样:
extension SomeType: SomeProtocol, AnotherProctocol {
// 协议实现写到这里
}
计算型属性
扩展可以为已有类型添加计算型实例属性和计算型类型属性。下面的例子为Swift
的内建Double
类型添加了五个计算型实例属性,从而提供与距离单位协作的基本支持:
extension Int {
var m: Int {
return self
}
var cm: Int {
return self * 100
}
var km: Int {
return self * 1_000
}
}
let threeKM = 3.km
print(threeKM) // 3000
扩展可以添加新的计算型属性,但是不可以添加存储型属性,也不可以为已有属性添加属性观察器。
构造器
扩展可以为已有类型添加新的构造器。这可以让你扩展其它类型,将你自己的定制类型作为其构造器参数,或者提供该类型的原始实现中未提供的额外初始化选项。
扩展能为类添加新的便利构造器,但是它们不能为类添加新的指定构造器或析构器。指定构造器和析构器必须总是由原始的类实现来提供。
extension CGRect {
init(center: CGPoint, size: CGSize) {
let originX = center.x - (size.width / 2)
let originY = center.y - (size.height / 2)
self.init(x: originX, y: originY, width: size.width, height: size.height)
}
}
let rect = CGRect(center: CGPoint(x: 50, y: 50), size: CGSize(width: 20, height: 20))
print(rect) // (40.0, 40.0, 20.0, 20.0)
如果你使用扩展提供了一个新的构造器,你依旧有责任确保构造过程能够让实例完全初始化。
方法
扩展可以为已有类型添加新的实例方法和类型方法。
extension Int {
func double() -> Int {
return self * 2
}
}
print(5.double()) // 10
可变实例方法
通过扩展添加的实例方法也可以修改该实例本身。结构体和枚举类型中修改self
或其属性的方法必须将该实例方法标注为mutating
,正如来自原始实现的可变方法一样。
// 报错 Cannot assign to value: 'self' is immutable
extension Int {
func square() {
self = self * self
}
}
// 正确方法
extension Int {
mutating func square() {
self = self * self
}
}
var someInt = 3
someInt.square() // 9
下标
扩展可以为已有类型添加新下标。
extension String {
subscript(_ digitIndex: Int) -> String {
if digitIndex < self.characters.count {
let index = self.index(self.startIndex, offsetBy: digitIndex)
return String.init(self[index])
}
return ""
}
}
let str = "abcdef"
print(str[2]) // c
嵌套类型
扩展可以为已有的类、结构体和枚举添加新的嵌套类型:
extension Int {
enum Kind {
case Negative, Zero, Positive
}
var kind: Kind {
switch self {
case 0:
return .Zero
case let x where x > 0:
return .Positive
default:
return .Negative
}
}
}
该例子为Int
添加了嵌套枚举。这个名为Kind
的枚举表示特定整数的类型。具体来说,就是表示整数是正数、零或者负数。
这个例子还为Int
添加了一个计算型实例属性,即kind
,用来根据整数返回适当的Kind
枚举成员。
现在,这个嵌套枚举可以和任意Int
值一起使用了:
func printIntegerKinds(_ numbers: [Int]) {
for number in numbers {
switch number.kind {
case .Negative:
print("- ", terminator: "")
case .Zero:
print("0 ", terminator: "")
case .Positive:
print("+ ", terminator: "")
}
}
print("")
}
printIntegerKinds([3, 19, -27, 0, -6, 0, 7])
// 打印 “+ + - 0 - 0 + ”