条件一致性
仅在满足约束时让泛型类型遵循协议。
条件一致性 是 CoddyKit 上的免费 Swift Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Swift Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Swift Academy 课程共包含 4 节课。
什么是条件遵循
条件遵循让泛型类型仅在其类型参数满足特定约束时遵循某个协议。经典示例是:只有当 Array 的 Element 遵循 Equatable 时,Array 才遵循 Equatable。
extension Array where Element: Equatable {
func allEqual(to x: Element) -> Bool {
allSatisfy { $0 == x }
}
}内置示例
标准库已经使用了这一机制:[Int] 遵循 Equatable,因为 Int 遵循该协议。两个数组会逐个元素进行比较,以判断是否相等。
let a = [1, 2, 3]
let b = [1, 2, 3]
print(a == b)声明条件遵循
请编写一个扩展,并通过 where 子句添加协议遵循。这里,只有当包装器的值类型也遵循 Equatable 时,包装器才遵循 Equatable。
struct Pair<T> {
let first: T
let second: T
}
extension Pair: Equatable where T: Equatable {
static func == (l: Pair, r: Pair) -> Bool {
l.first == r.first && l.second == r.second
}
}
print(Pair(first: 1, second: 2) == Pair(first: 1, second: 2))约束为何重要
如果没有该约束,编译器就无法合成 ==,因为比较包装的值要求该值本身可以进行比较。where 子句正好提供了这一保证。
struct Box<T> { let value: T }
extension Box: Equatable where T: Equatable {}
print(Box(value: "hi") == Box(value: "hi"))
print(Box(value: 5) == Box(value: 9))条件可编码遵循
您也可以有条件地遵循 Codable。只有当容器的元素遵循 Codable 时,容器才可编码。
struct Wrapper<T> { let payload: T }
extension Wrapper: Codable where T: Codable {}
let w = Wrapper(payload: 42)
let data = try! JSONEncoder().encode(w)
print(String(data: data, encoding: .utf8)!)多个约束
where 子句可以列出多个要求,并用逗号分隔。
struct Stack<T> { var items: [T] = [] }
extension Stack where T: Comparable {
func maxItem() -> T? { items.max() }
}
var s = Stack<Int>()
s.items = [3, 9, 1]
print(s.maxItem()!)条件 CustomStringConvertible 遵循
只有当一个类型的内容也支持打印时,才让该类型可打印,并根据各个元素组合出描述。
struct Labeled<T> { let label: String; let value: T }
extension Labeled: CustomStringConvertible where T: CustomStringConvertible {
var description: String { label + ": " + value.description }
}
print(Labeled(label: "Age", value: 30))嵌套的条件遵循
条件遵循可以组合:由 Int 组成的数组的数组遵循 Equatable,因为每一层都会传递这一约束。
let grid1 = [[1, 2], [3, 4]]
let grid2 = [[1, 2], [3, 4]]
print(grid1 == grid2)约束为另一个协议
where 子句可以要求元素遵循您定义的协议,从而启用基于该协议的行为。
protocol Priced { var price: Double { get } }
struct Item: Priced { let price: Double }
extension Array where Element: Priced {
var totalPrice: Double { reduce(0) { $0 + $1.price } }
}
print([Item(price: 1.5), Item(price: 2.5)].totalPrice)同类型约束
您可以使用 == 将关联类型约束为特定类型。这里的方法仅适用于由 String 组成的数组。
extension Array where Element == String {
func joinedUpper() -> String {
map { $0.uppercased() }.joined(separator: "-")
}
}
print(["a", "b", "c"].joinedUpper())编译器如何使用它
条件遵循让编译器只在协议的功能确实有效时才提供这些功能,因此泛型代码既安全又具有最大的可复用性。
struct Optional2<T> { let value: T? }
extension Optional2: Equatable where T: Equatable {
static func == (l: Optional2, r: Optional2) -> Bool { l.value == r.value }
}
print(Optional2(value: 1) == Optional2(value: 1))快速检查
请检查您对条件遵循的理解。
回顾
条件遵循使用 extension Type: Protocol where ...,仅在类型参数满足约束时才授予协议遵循。您了解了它在 Equatable、Codable 和 CustomStringConvertible 中的应用,以及协议约束、同类型约束(==)和嵌套约束。它能让泛型类型既安全又可复用。
常见问题解答
「条件一致性」课时是免费的吗?
是的 — 「条件一致性」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Swift Academy 课程的其余内容,请升级到 CoddyKit PRO。 Swift Academy 课程共包含 4 节课。
「条件一致性」这节课中我会学到什么?
仅在满足约束时让泛型类型遵循协议。 你通过在浏览器中直接运行的动手代码来练习 Swift Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Swift Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Swift Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「条件一致性」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Swift Academy 课中编写并运行代码吗?
能。每节 Swift Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。