Swift学习46:协议和扩展

张建 lol

在扩展里添加协议遵循

  • 你可以扩展一个 已存在的类 来遵循一个新的协议

  • 扩展可以添加新的 属性、方法和下标 到已存在的类型,并且允许你添加协议的任何需要

1
2
3
4
5
6
7
8
9
protocol TextRepresentable {
var textDesc: String { get }
}
// 扩展已存在类遵循新协议
extension Dice: TextRepresentable {
var textDesc: String {
return "zhangjian"
}
}

有条件的遵循协议

  • 泛型 可能只在某些情况下满足一个 协议 的要求

  • 泛型形式参数 遵循协议时。你可以通过 扩展 列出限制 泛型 有条件的遵循某协议。在协议名字后面写泛型 where 关键字

1

使用扩展声明协议

  • 如果一个 类型(类、结构体、枚举) 已经遵循了协议的所有需求,但还没有 声明它采纳这个协议,你可以通过 扩展来让它声明并采纳 这个协议

定义协议:

1
2
3
4
// 定义协议
protocol TextRepresentable {
var textDesc: String { get }
}

定义结构体类型:

1
2
3
4
5
6
7
struct Hamster {
var name: String
// 实现了 遵循协议的所有要求
var textDesc: String {
return "a hamster named \(name)"
}
}

可以通过 扩展 来让 Hamster 遵循 协议:

1
extension Hamster: TextRepresentable {}

协议本身扩展

  • 协议可以通过 扩展 来提供 属性、方法,即 协议本身支持扩展

示例:

【第一步】:定义一个随机数协议

1
2
3
4
// 定义协议
protocol RandomNumberGenerator {
func random() -> Double
}

【第二步】:生成随机数

1
2
3
4
5
6
7
8
9
10
11
// 生成随机数
class LinearCongruentialGenerator: RandomNumberGenerator {
var lastRandom = 42.0
let m = 139968.0
let a = 3877.0
let c = 29573.0
func random() -> Double {
lastRandom = ((lastRandom * a + c).truncatingRemainder(dividingBy:m))
return lastRandom / m
}
}

【第三步】:让协议本身扩展

1
2
3
4
5
6
// 协议本身支持扩展
extension RandomNumberGenerator {
func randomBool() -> Bool {
return random() > 0.5
}
}

【最后】:调用

1
2
3
4
5
6
7
let generator = LinearCongruentialGenerator()
print("here is random number \(generator.random())")
print("and here is random bool \(generator.randomBool())")

==========
here is random number 0.3746499199817101
and here is random bool true

提供默认实现

  • 可以使用 协议扩展 给协议的 属性或方法 提供默认实现。

  • 如果遵循协议的 类型 提供了自己的实现,会 替代协议扩展中的实现

给集合类和其中的元素添加 协议扩展

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 有条件的遵循协议
protocol TextRepresentable {
var textDesc: String { get }
}
// 定义一个结构体 Person
struct Person {
var name:String = ""
}
// 扩展 Person 遵循协议
extension Person: TextRepresentable{
var textDesc: String {
return "name \(name)"
}
}
// 扩展数组元素都遵循协议
extension Array: TextRepresentable where Element: TextRepresentable {
var textDesc: String {
let items = self.map { $0.textDesc }
return items.joined(separator: ",")
}
}
let array = [Person(name: "zj"),Person(name: "wxy")]
print(array.textDesc)

==========
name zj,name wxy

给 协议扩展 添加限制

  • 扩展协议后 面用 where 来写这些限制

将上面的 Array 改成 Collection协议,查看打印结果

1
2
3
4
5
6
7
8
9
10
// 扩展数组元素都遵循协议
extension Collection where Iterator.Element: TextRepresentable {
var textDesc: String {
let items = self.map { $0.textDesc }
return items.joined(separator: ",")
}
}

==========
name zj,name wxy

总结

  • 除了可以给具体的 类、结构体 扩展以外,还可以 扩展协议本身
  • Post title:Swift学习46:协议和扩展
  • Post author:张建
  • Create time:2023-03-05 17:05:03
  • Post link:https://redefine.ohevan.com/2023/03/05/Swift课程/Swift学习46:协议和扩展/
  • Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.