Dart控制流主要由循環和分支組成:
- Dart官方文檔-循環:https://dart.dev/language/loops
- Dart官方文檔-分支:https://dart.dev/language/branches
重要説明:本博客基於Dart官網文檔,但並不是簡單的對官網進行翻譯,在覆蓋核心功能情況下,我會根據個人研發經驗,加入自己的一些擴展問題和場景驗證。
循環
Dart可通過循環來控制邏輯流,它支持3種語句:for循環,while和do while循環,break和continue等
同時,也可以通過非循環來控制邏輯流,包括:分支(如:if和switch)和異常(try、catch和throw)等
for循環
for循環可以使用在迭代中,標準用法如下代碼樣例:
var message = StringBuffer('Dart is fun');
for (var i = 0; i < 5; i++) {
message.write('!');
}
for-in循環常用於無需關注迭代的索引,如下代碼樣例,包含了閉包列表和迭代:
var callbacks = [];
for (var i = 0; i < 2; i++) {
callbacks.add(() => print(i));
}
for (final c in callbacks) {
c();
}
// 解構:01
同樣的,for-in循環還可以使用對象模式(Pattern模式詳解:https://ntopic.cn/p/2023100501),解構迭代的元素:
for (final Candidate(:name, :yearsExperience) in candidates) {
print('$name has $yearsExperience of experience.');
}
對於迭代類型(Dart可迭代集合詳解:https://ntopic.cn/p/2023092701),forEach()方法也可以實現循環:
var collection = [1, 2, 3];
collection.forEach(print); // 1 2 3
while和do while循環
while循環和do while循環最大的區別:while先檢測循環條件,然後執行循環邏輯;do while默認先執行1次循環邏輯,然後檢測循環條件,以決定後續是否繼續執行循環邏輯。
while (!isDone()) {
doSomething();
}
do {
printLine();
} while (!atEndOfPage());
break和continue循環控制
break和continue在循環中的最大區別:break中斷整個循環,而continue中斷當前循環的後續邏輯。
while (true) {
if (shutDownRequested()) break;
processIncomingRequests();
}
for (int i = 0; i < candidates.length; i++) {
var candidate = candidates[i];
if (candidate.yearsExperience < 5) {
continue;
}
candidate.interview();
}
// 若`candidates`是可迭代列表,則上面的邏輯可改寫如下:
candidates
.where((c) => c.yearsExperience >= 5)
.forEach((c) => c.interview());
分支
Dart也可通過分支來控制邏輯流:if語句和元素,if-case語句和元素,switch語句和switch表達式等。
同樣的,我們也可以通過其他方式來控制邏輯流:如循環(就是本文的第1節)和異常(try、catch和throw)等
if/else分支
if語句可以有else可選項子句,if後面的括號中的表達式計算值必須是boolean類型,如下代碼樣例:
if (isRaining()) {
you.bringRainCoat();
} else if (isSnowing()) {
you.wearJacket();
} else {
car.putTopDown();
}
if-case模式
Dart中if語句後的case子句可以帶一個模式(Pattern模式詳解:https://ntopic.cn/p/2023100501):
if (pair case [int x, int y]) return Point(x, y);
上訴代碼樣例中,列表模式[int x, int y]首先匹配pair值,並且把列表第1和第2個int類型的元素解構並賦值給了x和y變量。
如果模式未能成功匹配,則需要進入else分支:
if (pair case [int x, int y]) {
print('Was coordinate array $x,$y');
} else {
throw FormatException('Invalid coordinates.');
}
switch語句和switch表達式
switch語句後面可以有多個case子句,每一個case子句都可以是一個模式(Pattern模式詳解:https://ntopic.cn/p/2023100501)。
當沒有case子句匹配時,就會執行default子句或者_通配符子句:
switch (command) {
case 'OPEN':
executeOpen();
continue newCase; // 繼續執行
case 'DENIED':
case 'CLOSED':
executeClosed(); // `DENIED`和`CLOSED`均會執行
newCase:
case 'PENDING':
executeNowClosed(); // `OPEN`和`PENDING`均會執行
}
在switch語句中,還可以使用模式,有如下幾種用法:
var x = switch (y) { ... };
print(switch (x) { ... });
return switch (x) { ... };
switch表達式可以重寫switch語句,如下為switch語句的代碼樣例:
// `slash`, `star`, `comma`, `semicolon`等,需要是常量
switch (charCode) {
case slash || star || plus || minus: // `邏輯或`模式
token = operator(charCode);
case comma || semicolon: // `邏輯或`模式
token = punctuation(charCode);
case >= digit0 && <= digit9: // `關係`和`邏輯與`模式
token = number();
default:
throw FormatException('Invalid');
}
上訴代碼樣例,可以使用switch表達式重寫如下:
token = switch (charCode) {
slash || star || plus || minus => operator(charCode),
comma || semicolon => punctuation(charCode),
>= digit0 && <= digit9 => number(),
_ => throw FormatException('Invalid')
};
switch表達式不同於switch語句的語法,包括以下幾個方面:
- Case可選項無需使用
case開頭。 - Case可選項的邏輯是一個表達式,而不是一系列的語句。
- Case可選項都必須有邏輯,空可選性不代表隱性失敗。
- Case可選項模式,邏輯使用
=>分割。 - 多個Case可選項之間,使用
,分割。 - 默認可選項,只能使用
_。
Switch還可以使用在窮舉檢測中,就是所有的值都有對應的可選項被處理,以避免引發編譯錯誤。默認可選項(default或_)涵蓋了所有其他情況,因此它可以保障窮舉性。
case-when子句
case-when子句:在case子句後面增加when子句。case-when子句可以用在if-case、switch語句和switch表達式中。
switch (pair) {
case (int a, int b) when a > b:
print('First element greater');
case (int a, int b):
print('First element not greater');
}
case-when子句計算任何一個boolean類型的值,值為true代表可以執行本Case可選項邏輯,為false則繼續執行下一個Case可選項,並不會退出整個Switch語句。
我的本博客原地址:https://ntopic.cn/p/2023101301