协议扩展
本课属于 Coddy Swift 学习旅程的“面向对象编程”单元。第 29 课,共 57 课。
协议扩展为协议的方法提供默认实现。所有遵循该协议的类型都可以免费获得这个实现,而且类型仍然可以提供自己的实现:
protocol Greeter {
var name: String { get }
func greet() -> String
}
extension Greeter {
func greet() -> String { "Hello, \(name)!" }
}
struct English: Greeter { let name: String }
struct Pirate: Greeter {
let name: String
func greet() -> String { "Ahoy, \(name)!" }
}
print(English(name: "Ada").greet())
print(Pirate(name: "Ada").greet())输出:
Hello, Ada!
Ahoy, Ada!扩展还可以添加仅根据要求构建的新方法。符合要求的类型只需编写少量必需部分,就能获得其余功能:
protocol Scored {
var points: [Int] { get }
}
extension Scored {
var total: Int { points.reduce(0, +) }
var best: Int { points.max() ?? 0 }
func summary() -> String { "total \(total), best \(best)" }
}
struct Player: Scored {
let points: [Int]
}
print(Player(points: [3, 9, 4]).summary())输出:
total 16, best 9这让结构体、类和枚举可以共享行为,而无需继承。标准库的工作方式也一样:每个 Collection 都会通过协议扩展获得 isEmpty、first 和 map。
extension Collection {
// isEmpty、first、map、filter 等都只需在这里定义一次
// 每个数组、集合、字典和字符串都能使用它们
}受约束的扩展只为符合条件的类型添加方法,使用 where 编写:
protocol Container {
associatedtype Item
var items: [Item] { get }
}
extension Container where Item == Int {
var sum: Int { items.reduce(0, +) }
}
struct Box: Container {
var items: [Int]
}
print(Box(items: [2, 5]).sum)输出:
7挑战
简单声明一个协议 Priced,要求包含 var price: Int { get }(以分为单位)和 var formatted: String { get }。在协议扩展中,为 formatted 提供一个默认实现,返回 $4.50,并添加一个方法 isAffordable(budget:),用于判断价格是否在预算范围内。让结构体 Coffee(价格为 450)和 Sandwich(包含一个存储属性 price)遵循该协议。Coffee 必须将默认的 formatted 替换为 coffee $4.50。
提供的代码会读取预算,然后读取内容为 coffee 或 sandwich,650 的行。对于每件商品,代码会输出 formatted,以及 yes 或 no。
你的代码应写在 Priced.swift、Coffee.swift 和 Sandwich.swift 中。main.swift 包含提供的输入/输出代码,不能编辑。
亲手试试
// 提供的输入/输出代码:保持原样
var input: [String] = []
while let line = readLine() { input.append(line) }
let budget = Int(input[0])!
for line in input.dropFirst() {
let item: any Priced = line == "coffee" ? Coffee() : Sandwich(price: Int(line.split(separator: ",")[1])!)
print("\(item.formatted) \(item.isAffordable(budget: budget) ? "yes" : "no")")
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Swift 在线编辑器