Swift中的模式匹配

1、其中匹配模式

通配符模式

忽略匹配的值

_

_?:匹配值不能是nil,可匹配可选值,表示确保存在

标示模式

匹配一个具体的值

case 5: ....

值绑定

case let ... :

元组模式

同时匹配多个值

1
2
3
4
//提取age,确保job存在、payload是NSDictionary类型
switch (age, job, payload) {
case (let age, _?, _ as NSDictionary): ...
}

枚举case

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
enum Entities {
case Soldier(x: Int, y: Int)
case Tank(x: Int, y: Int)
case Player(x: Int, y: Int)
}
for e in entities() {
switch e {
case let .Soldier(x, y):
drawImage("soldier.png", x, y)
case let .Tank(x, y):
drawImage("tank.png", x, y)
case let .Player(x, y):
drawImage("player.png", x, y)
}
}

类型转换模式

  • is 类型:匹配右手边内容的运行时类型(或者类型的子类)。它会做类型转换但是不关注返回值。所以你的 case 块不知道所匹配的类型是什么。
  • 模式 as 类型:和 is 模式做同样的匹配操作,但是如果成功的话会把类型转换到左侧指定的模式中。
1
2
3
4
5
6
7
8
9
let a: Any = 5 
switch a {
// 这会失败因为它的类型仍然是 `Any`
// 错误: binary operator '+' cannot be applied to operands of type 'Any' and 'Int'
case is Int: print (a + 1)
// 有效并返回 '6'
case let n as Int: print (n + 1)
default: ()
}

表达模式

case <expresion>

可以通过重写~=操作符来实现自定义的表达式:

1
2
3
4
5
6
7
8
9
10
11
12
protocol Entity { var value: Int {get} }
struct Tank: Entity { var value: Int }
struct Peasant: Entity { var value: Int }

func ~=(pattern: Entity, x: Entity) -> Bool {
return pattern.value == x.value
}

switch Tank(42) {
case Peasant(42): print("Matched") // 匹配成功
default: ()
}

2、if、for、guard语句中的case

1
2
3
4
5
6
7
enum Entity {
enum EntityType {
case Soldier
case Player
}
case Entry(type: EntityType, x: Int, y: Int, hp: Int)
}

for case

1
2
3
4
for case let Entity.Entry(t, x, y, _) in gameEntities()
where x > 0 && y > 0 {
drawEntity(t, x, y)
}

guard case

1
2
3
4
5
6
func healthHP(entity: Entity) -> Int {
guard case let Entity.Entry(.Player, _, _, hp) = entity
where hp < MAX_HP
else { return 0 }
return MAX_HP - hp
}

if case

1
2
3
4
5
6
7
func move(entity: Entity, xd: Int, yd: Int) -> Entity {
if case Entity.Entry(let t, let x, let y, let hp) = entity
where (x + xd) < 1000 && (y + yd) < 1000 {
return Entity.Entry(type: t, x: (x + xd), y: (y + yd), hp: hp)
}
return entity
}

解构类和结构体

定义unapply方法来解构,和init功能相反

1
2
3
4
5
6
7
8
9
10
struct Imaginary {
let x: Int
let y: Int
func unapply() -> (Int, Int) {
// 实现这个方法之后,理论上来说实现了解构变量所需的所有细节
return (self.x, self.y)
}
}
// 然后这个就会自动 unapply 然后再进行匹配
guard case let Imaginary(x, y) = anImaginaryObject else { break }
0%