本文是Dart語言學習的第12天,和前面11天相比,本文可能相對比較簡單,因為本文要學習的是Dart語言的控制流,也就是迴圈和分支。且前面的11天學習中,多多少少都涉及到了控制流,同時對Java或者JavaScript比較熟悉的朋友,可能比較容易上手…… ...
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
本文作者:奔跑的蝸牛,轉載請註明原文鏈接:https://ntopic.cn