經過前兩回的 Dart 教學,相信大家已經掌握 Dart 變數、流程控制和一些常用的容器,這次的教學會著重在函式 Function
的部分,在 Dart 中,函式的寫法比較多種,除了像一般 C, Java, Javascript, Go 等語言基礎的寫法,也支援更彈性的操作,比如可命名參數的 Fucntion,或者可選位置參數的 Fucntion。
這種作法可以實現 C++, Java 中的 overload。傳統的 overload 雖然學習上方便,但可能會讓程式碼變得很複雜,而且在調用時也必需再三確認文件。Dart 的作法與 Python 類似,在 Python 中,Function 可以使用預設參數或不定參數來模擬 overload 的行為。
在 Flutter 中,由於有很多參數可以進行調整,因此經常使用可命名參數的 Function。掌握 Dart 中特有的 Function 寫法對於後續 Flutter 的學習相當重要!
範例程式碼:https://github.com/ksw2000/ironman-2024
官方教學文件:https://dart.dev.org.tw/language/functions
在 Dart 中,函式的使用和 Java 的寫法類似,但是又多了更多的功能,以下是一個試範:
int add(int a, int b) {
return a + b;
}
void main() {
print(add(3, 4));
}
其中,函式 add
的輸出為 int
,而輸入 a, b
也都為 int
。而 main()
則是 dart 預設執行的函式。跟 C, Java, Go, Typescript 一樣,對於那些沒有回傳值的函式我們可以使用 void
來表示。
另外,我們也可以利用 =>
簡化函式的寫法
int add2(int a, int b) => a + b;
函式本身也屬於一個 Function
型別,所以我們可以將 Function 當做參數傳入 function。
void add3(int a, int b, Function callback) {
callback(a + b);
}
void main(){
add3(4, 5, (n) {
print(n);
});
// 編譯成功,但執行時會報錯
// add3(6, 7, (m, n)){
// print("$m $n");
// }
// Unhandled exception:
// NoSuchMethodError: Closure call with mismatched arguments: function 'main.<anonymous closure>'
}
直接以 Function 來傳送可能會有一個問題,那就是使用者不知道該設計怎樣的 function,比如上述的例子中,callback
的型態其實應該是 void callback(int)
,也因此我們可以換成以下的寫法:
void add4(int a, int b, void Function(int) callback) {
callback(a + b);
}
void main(){
add4(6, 7, (e) {
print(e);
});
}
在 Flutter 中,有些時候因為函式的功能很強大,所以會有非常多參數可以調整,但是要調整時,我們會記不住他的位置,而且有些參數會有預設值,不需要使用者自己設定,此使我們可以使用「可命名參數」,這類參數會要求使用者在調用函式時寫上參數的名字,而不是靠位置決定。
int add5({int? a, int? b}) {
int aa = a ?? 0;
int bb = b ?? 0;
return aa + bb;
}
void main(){
print(add5(a: 2)); // 2
print(add5(b: 3)); // 3
print(add5(a: 2, b: 3)); // 5
}
由於使用者可以不填入 a
或不填入 b
,因此在接收函式時,要使用 int?
而不是 int
。當使用者沒有決定其中一個參數時,預設就是傳送 null
。此時你可能會有疑問,我們不能自己更改預設值嗎?其實是可以的
int add6({int a = 0, int b = 0}) {
return a + b;
}
另外,我們也可以要求使用者一定要填寫某個參數。只要在參數前加上 required
即可,這樣使用這就一定得輸入該參數。比如我們可以要求使用者一定要使用參數 a
。早期的 Dart 1.x 似乎沒有這個功能,這個功能原本是 Flutter 利用裝飾器實作的,當時會使用 @required
來表示該參數必選,後來才逆輸入給 Dart 的編譯器。
int add7({required int a, int b = 0}) {
return a + b;
}
void main(){
add7(a: 3); // 3
add7(b: 3); // 編譯不過
}
有時候,我們只有最後幾個參數供使用者選擇,此時我們可以利用中括號 []
,將這些可有可無的參數提供給使用者。
int add8(int a, [int? b, int? c]) {
return a + (b ?? 0) + (c ?? 0);
}
void main(){
print(add8(2)); // 2
print(add8(2, 3)); // 5
print(add8(2, 3, 4)); // 9
}
跟上一節的寫法類似,我們仍然可以提供預設值給那些參數
int add9(int a, [int b = 0, int c = 0]) {
return a + b + c;
}
後記:原本今天想講一些 class,但感覺留在明天講比較段落分明?