首页 / Swift 编程语言教程 / switch 语句(基础)

Swift 编程语言教程

switch 语句(基础)

本教程共 93 篇 · 第 22 篇 · 更新于 2026-08-08 · 约 8 分钟阅读

SwiftSwift 编程语言教程switch分支匹配default穷尽匹配复合case无隐式贯穿

本节目标:掌握 switch 的基本结构,理解“必须穷尽所有情况”和“匹配即结束、不会掉进下一个 case”这两条核心规则。

if 适合处理两三个分支。一旦要判断的情况变多,一长串 else if 会又臭又长。Swift 的 switch 就是为这种“多分支按值匹配”的场景准备的,而且它比 C、Java 里的 switch 强得多。基础章节先把骨架搭好,进阶章节再上威力更大的匹配模式。

1-1 switch 长什么样

switch 后面跟一个要被检查的值,花括号里是一个个 case。每个 case 写一个或一组可能匹配的值,命中后就执行对应的代码。

let someCharacter: Character = "z"
switch someCharacter {
case "a":
    print("拉丁字母的第一个")
case "z":
    print("拉丁字母的最后一个")
default:
    print("其他字符")
}

这里 someCharacter 是字符 "z",依次和各个 case 比较,命中 case "z" 就打印对应内容。switch 走完就结束,不会继续往后跑。读起来就像在说“这个值,是 a 就怎样,是 z 就怎样,否则怎样”。

1-2 必须穷尽:所有情况都得有人接

这是 Swift switch 最重要的一条铁律:必须穷尽(exhaustive)。也就是说,被检查的值所有可能的结果,都得被某个 case 覆盖到。

上面的例子里,字符远不止 az。所以不能只写这两个 case,必须加一个 default 来兜住其余所有情况。default 用关键字 default 表示,而且必须放在最后。

如果忘写 default,或者某个可能的值没被覆盖,编译器会直接报错,不让你跑。这其实是好事——它强迫你在写代码时就想清楚“剩下的情况怎么办”,而不是等到运行时才措手不及。很多运行时崩溃,根子就是当初漏考虑了某种输入。

Note

当你匹配的是枚举(后面会讲),而枚举的每个成员都写了 case,就可以不写 default,因为枚举本身就穷尽了。但匹配 IntString、字符这类开放类型时,default 几乎总是必需的。

1-3 没有隐式贯穿:命中即结束

如果你写过 C 或 Objective-C,会记得每个 case 末尾得写 break,否则会“贯穿”到下一个 case。Swift 完全反过来:默认不会贯穿

只要第一个匹配的 case 执行完,整个 switch 就结束了,不需要写 break。这让代码更安全,也避免了手滑同时跑了多个分支。C 里忘记写 break 是经典 bug,Swift 从语言层面消灭了它。

let anotherCharacter: Character = "a"
let message = switch anotherCharacter {
case "a":
    "拉丁字母的第一个"
case "z":
    "拉丁字母的最后一个"
default:
    "其他字符"
}
print(message)

这是 switch 的“表达式”形式:每个 case 直接写一个值,整体结果赋给 message。和 if 表达式一样,它要求每个分支产出同类型的值。表达式形式和语句形式你都会见到,本质相同,只是表达式能直接当值用。

1-4 每个 case 不能为空

Swift 不允许出现空的 case。下面这种写法会编译报错:

let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a":          // 错误:这个 case 体是空的
case "A":
    print("字母 A")
default:
    print("不是字母 A")
}

编译器会告诉你 case "a": 里没有任何可执行的语句。它这么做是为了防止你误以为 "a""A" 会一起命中——在 Swift 里它们不会。想让一个 case 同时匹配多个值,要用下面说的复合写法。

1-5 复合 case:一个分支匹配多个值

想让一个分支同时接住 "a""A",用逗号把值列在一起,这就是“复合 case”。

let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a", "A":
    print("字母 A")
default:
    print("不是字母 A")
}

值之间用逗号分隔,命中其中任意一个就执行该分支。值多的时候也能写成多行,可读性更好:

let vowel: Character = "e"
switch vowel {
case "a", "e", "i", "o", "u":
    print("\(vowel) 是元音")
default:
    print("\(vowel) 不是元音")
}
Tip

复合 case 是“或”的关系:匹配清单里任意一个即可。它和 if 里的逻辑或 || 思路一致,只是写在了 switch 里更整齐,尤其当清单较长时优势明显。

1-6 想忽略某个 case 时用 break

前面说 Swift 不需要 break。但在一种情况下你会用到它:刻意匹配某个 case 却什么都不做,纯粹为了“表明我考虑过这种情况”。

let numberSymbol: Character = "三"
var possibleIntegerValue: Int?
switch numberSymbol {
case "1", "١", "一", "๑":
    possibleIntegerValue = 1
case "2", "٢", "二", "๒":
    possibleIntegerValue = 2
default:
    break
}

这里 default 分支什么都不用做,于是只写一个 break。注意:只写注释不算语句,编译器仍会报空 case 错误,所以必须用 break 来占位。break 在这里的作用就是“匹配到了,但立即结束 switch”。

1-7 和 if 该怎么选

粗略的经验:if 适合判断“一个条件成立不成立”,尤其条件是基于范围或布尔逻辑时。switch 适合“这个值等于哪些离散的可能”,分支多的时候最清爽。

比如判断分数是“优秀、良好、及格、不及格”,用 switch 配区间(下一章会讲)就很顺;判断“是否成年”这种单一布尔条件,用 if 更直接。两者并非互斥,熟练之后你会凭直觉在两者间切换。

1-8 switch 和枚举是天生一对

等你学到枚举(enum)会发现,switch 和它配合最默契。枚举的成员是有限的、已知的,比如表示方向的 northeastsouthwest。当你为枚举的每个成员都写了一个 case,编译器就能确认已经穷尽,于是连 default 都不用写。

反过来,如果哪天你给枚举加了一个新成员,却忘了在 switch 里加对应分支,编译器会直接报错提醒你。这种“编译器兜底”的特性,让 switch 成为处理枚举的首选方式,也是 Swift 类型安全的重要体现。

1-9 编译器替你查漏

穷尽性检查发生在编译阶段,不是运行时。也就是说,漏掉的情况在你还没跑程序时就被拦下了。这比靠测试去碰运气可靠得多。

写 switch 时不用怕分支多,反而应该欢迎分支多——把每种情况摊开写清楚,编译器帮你看着有没有遗漏。这也是 Swift 强调“能在编译期发现的错误,就不要留到运行时”的一贯风格。把判断逻辑显式写出来,既方便编译器检查,也方便后来的人读。

理解了基础结构,switch 真正的威力还在后面——区间匹配、元组、值绑定、where 子句,下一章接着讲。这些进阶玩法才是 Swift switch 甩开其他语言的地方。

学完这章你可以做件小事巩固一下:找一个原来用 if-else 链写的判断,试着改写成 switch。改写过程中你会真切体会到“穷尽性”带来的安全感——编译器不再让你漏情况,漏了它当场报错。下一章我们把区间、元组这些更强的模式加上去,那时你会发现 switch 能表达的东西远比一堆等号比较要丰富。