0%

谈谈 Swift 中的 Switch

Swift 这门语言在很多方面相对于 Objective-C 都是有很大的加强,影响巨大的如 协议结构体枚举函数 等,这些使得 Swift 敢于宣称自己支持 面向协议的编程面向函数的编程;其实即使在一些细碎的地方,Swift 仍然有很多值得称道的点,Switch 语句就是其中一个。

Switch 在 Objective-C 中的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
typedef enum : NSUInteger {
QWPDirectionEast,
QWPDirectionSouth,
QWPDirectionWest,
QWPDirectionNorth
} QWPDirection;

QWPDirection direction = QWPDirectionWest;

switch (direction) {
case QWPDirectionEast:
NSLog(@"east");
break;
case QWPDirectionSouth:
NSLog(@"south");
break;
case QWPDirectionWest:
NSLog(@"west");
break;
case QWPDirectionNorth:
NSLog(@"north");
break;
}

在 Objective-C 中,Switch 语句很多时候会搭配枚举使用,这是因为枚举在 Objective-C 中只能为整型,而 Switch 的 condition 也必须为整型。

这里的 Switch 可以总结如下几个特征:

  • condition 必须为整型;
  • 每个 case 必须互斥;
  • 如果不希望穿透,就必须写 break。

Swift 中的 Switch

在 Swift 中,相对于 Objective-C:

  • condition 不仅仅可以为整型,几乎可以为任何类型,如 String、Double,甚至是 Tuple;
  • case 之间不必一定互斥,只要所有的 case 可以包含所有的情况就可以;
  • 默认不能穿透;

既然不能穿透了,那么如果我们希望实现类似 Objective-C 中的穿透该怎么做呢?事实上把希望执行相同代码的情况用逗号分隔就好了。如下面的例子:

1
2
3
4
5
6
7
8
9
10
11
12
let level = "A"

switch level {
case "A", "a":
print("优")
case "B", "b":
print("良")
case "C", "c":
print("一般")
default:
print("错误")
}

其实 Swift 中是有一个穿透的关键字的,叫做 fallthrough,之前看过有人用这个关键字模仿 Objective-C 的写法,即 Objective-C 中不写 break 的地方,Swift 中就加上 fallthrough 实现穿透。

其实这样不太好,并不是 fallthrough 最合理的使用场景,因为大多情况下只需要将不同的 case 通过逗号分隔写在一行就好了,为何还要 fallthrough 呢?

这就涉及到 Swift 中的 Switch 的另一个特征了,就是 case 之间可以不必互斥,这就是两个 case 之间可以存在公共部分,甚至一个 case 可以是另一个 case 的子集。这就给我们更多的可能性去实现之前无法实现的逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
let vector: (x: Int, y: Int) = (0, 0)

switch vector {
case (0, 0):
print("原点")
fallthrough
case (_, 0):
print("x轴")
default:
print("其他")
}

// 最终打印:原点 x轴

上面这个例子,第一个 case 是 第二个 case 的真子集,当第一个 case 满足的时候,第二个 case 一定满足(反之不成立),这就是一个使用 fallthrough 的好时机,因为原点也在x轴上嘛。

case 语句中也不仅仅可以填写确定的值,甚至可以增加条件,如:

1
2
3
4
5
6
7
8
let vector: (x: Int, y: Int) = (0, 0)

switch vector {
case let (x, y) where x == y:
print("在 x = y 的线上")
default:
print("其他")
}