Swift 5.1 (19) - 扩展
扩展:在不需要访问源码的情况下,为现有的类,结构,枚举或协议类型添加了新功能。和Objective-C
的分类很类似,不同的是Swift的扩展没有名称。
Swift的扩展具备的能力:
- 添加实例计算属性和类计算属性
- 定义实例方法和类方法
- 提供新的初始化方法
- 定义下标
- 定义和使用新的嵌套类型
- 使现有类型遵守某个协议
注意:扩展可以给一个类型添加新的功能,但是不能覆盖现有功能。
Extension
语法
声明扩展需要使用Extension
关键字:
extension SomeType {
// 可添加扩展的功能
}
扩展可以扩展现有类型以使其采用一个或多个协议。
extension SomeType: SomeProtocol, AnotherProtocol {
// 可添加协议要求的实现
}
注意:如果定义扩展为现有类型添加新的功能,则此新功能在所有该类型已存在的实例上都是可用的,即使实例在定义扩展之前被创建。
计算属性
扩展可以添加实例计算属性和类计算属性。下例向Swift的内置Double
类型添加了五个计算实例属性作为距离单位:
extension Double {
var km: Double { return self * 1_000.0 }
var m: Double { return self }
var cm: Double { return self / 100.0 }
var mm: Double { return self / 1_000.0 }
var ft: Double { return self / 3.28084 }
}
let oneInch = 25.4.mm
print("一英寸是 \(oneInch) 米")
// Prints "一英寸是 0.0254 米"
let threeFeet = 3.ft
print("三英尺是 \(threeFeet) 米")
// Prints "三英尺是 0.914399970739201 米"
let aMarathon = 42.km + 195.m
print("马拉松长 \(aMarathon) 米")
// Prints "马拉松长 42195.0 米"
注意:扩展可以添加新的计算属性,但是不能添加存储属性,也不能为现有属性添加属性观察者。
初始化方法
扩展可以为现有类型添加初始化方法。
扩展也可以为一个Class
类型添加新的便利初始化方法,但是不能为一个Class
类型添加新的指定初始化方法或反初始化方法。指定初始化方法或反初始化方法必须由原始的类实现。
如果使用扩展为值类型添加一个初始化方法,该值类型为其所有存储属性提供了默认值,并且没有自定义的初始化方法,则我们可以在该值类型扩展中的初始化方法里调用默认的初始化方法或调用按成员生成的初始化方法。若值类型原始实现时,提供了自定义的初始化方法,则在该值类型扩展中的初始化方法里调用其自定义的初始化方法。
注:若想自定义的值类型既能调用默认初始化又能调用成员初始化还要能调用自定义的初始化,则这个自定义的初始化方法必须写在extension
中。
如果使用扩展为声明在其他模块的结构体添加初始化方法,则新的初始化方法不能访问self
属性,直到该结构体从其定义的模块中调用了初始化方法。
struct Size {
var width = 0.0, height = 0.0
}
struct Point {
var x = 0.0, y = 0.0
}
struct Rect {
var origin = Point()
var size = Size()
init(origi:Point,siz:Size) {
origin = origi
size = siz
}
}
extension Rect {
init(center:Point,size:Size) {
let originX = center.x - (size.width / 2)
let originY = center.y - (size.height / 2)
self.init(origi: Point(x: originX, y: originY), siz: size)
//! `Rect`原始定义中未自定义初始化方法则此处应该使用默认初始化方法或者成员初始化方法:`self.init(origin: Point(x: originX, y: originY), size: size)`
}
}
方法
扩展为现有类型添加实例方法和类方法。
extension Int {
func repetitions(task: () -> Void) {
for _ in 0..<self {
task()
}
}
}
//调用 输出三次`Hello!`
3.repetitions {
print("Hello!")
}
可变的实例方法
值类型扩展中可以添加使用mutating
修饰的实例方法,允许修改实例本身。
extension Int {
mutating func square() {
self = self * self
}
}
var someInt = 3
someInt.square() // someInt : 9
下标
扩展可以为现有类型添加新的下标。
//倒序输出一个整型数
extension Int {
subscript(digitIndex:Int)->Int {
var baseNum = 1
for _ in 0..<digitIndex {
baseNum *= 10
}
assert(baseNum <= self, "整数的索引越界了")
return (self/baseNum)%10
}
}
print(123456[5]) // 1
嵌套类型
扩展可为现有类,结构体,枚举添加新的嵌套类型。
extension Int {
enum Status : String,CaseIterable {
case NoAuth = "NoAuth"
case RequestError = "RequestError"
case None = "None"
}
var netStatus : String {
switch self {
case 401:
return Status.NoAuth.rawValue
case let x where x >= 500 :
return Status.RequestError.rawValue
default:
return Status.None.rawValue
}
}
}
print(401.netStatus) //!< NoAuth
print(500.netStatus) //!< RequestError
print(402.netStatus) //!< None
参考资料:
swift 5.1官方编程指南