假设你想给 Swift 标准库 — 比如说Double
类型添加额外的方法, 但是你又不知道Double
的实现, 所以你不能直接给它添加功能。 你改怎么办呢?
Swift 设计了一个叫做 Extensions 的功能来处理这样的情况。 Extensions 允许你为已经存在的类型添加功能。你可以扩展结构体、枚举和类。
你可以使用如下结构来扩展类型:
- 计算型属性
- 新的初始化方法
- 协议的遵守
- 新的方法
- 嵌入类型
扩展一个已经存在的类型
Swift 的扩展不允许你给已存在的类型添加存储属性, 但可以添加计算型属性。
typealias Velocity = Double
extension Velocity {
var kph: Velocity { return self * 1.60934 }
var mph: Velocity { return self }
}
// 为已存在的类型添加要遵守的协议
protocol VehicleType {
var topSpeed: Velocity { get }
var numberOfDoors: Int { get }
var hasFlatbed: Bool { get }
}
VehicleType声明了三个属性, topSpeed, numberOfDoors 和 hasFlatbed。每个属性都要求遵守该协议的类型只需为该属性实现 getter 方法。遵守该协议的类型需要提供协议中声明的这些属性。
扩展你自己的类型
添加一个自定义的类型:
typealias Velocity = Double
extension Velocity {
var kph: Velocity { return self * 1.60934 }
var mph: Velocity { return self }
}
protocol VehicleType {
var topSpeed: Velocity { get }
var numberOfDoors: Int { get }
var hasFlatbed: Bool { get }
}
struct Car {
let make: String
let model: String
let year: Int
let color: String
let nickname: String
var gasLevel: Double {
willSet {
precondition(newValue <= 1.0 && newValue >= 0.0,
} }
"New value must be between 0 and 1.")
}
gasLevel 是一个可变的含有属性观察器的存储属性。每次你想要给 gasLevel设置一个新值的时候都会调用 willSet
观察器。precondition()函数确保被赋值给 gasLevel 属性的 newValue 在区间 0到1 之内。
给类添加扩展以使其遵守协议
扩展提供了很好的机制来把相关的功能块儿归为一组。在单个扩展中把相关功能片段归为一组可以让你的代码可读性更好, 并且更容易维护。
下面扩展 Car 类型使其遵守 VeicleType 协议。
extension Car: VehicleType {
var topSpeed: Velocity { return 180 }
var numberOfDoors: Int { return 4 }
var hasFlatbed: Bool { return false }
}
你在extension的主体里面实现了协议的必要属性。每个属性给了一个简单的 getter, 为了方便, 你仅仅返回简单的默认值。
使用扩展给已存在的类添加 initializer
还记得吗, 结构体给了你一个免费的逐个成员初始化函数, 如果你自己每提供的话。如果你想为你的结构体写一个新的 initializer 函数, 但是又不想失去那个免费的逐个成员初始化函数, 你可以使用扩展为你的类型添加一个 initializer 函数。
下面在新的扩展中给Car添加一个initializer 函数: