前面的章節有提到過,在 Dart 中,函式也是一個物件,它的型別是 Function。
它可以被賦值給變數,可以被作為引數傳遞。
宣告一個函式
這是個常規的函式宣告:
bool isNoble(int atomicNumber) {
return atomicNumber != null;
}
複製程式碼
如果一個函式沒有顯示宣告返回值,Dart 會自動推導它的返回值型別。
void main() { bool b = isNoble(2); print(b); } isNoble(int atomicNumber) { return atomicNumber != null; } >>> true 複製程式碼
如果一個函式沒有顯示的
return
,那麼它預設會返回 null。fun(){} assert(fun() == null) 複製程式碼
如果一個函式只有一句表示式,可以使用簡寫:
bool isNoble(int atomicNumber) => atomicNumber != null; isNoble(int atomicNumber) => atomicNumber != null; 複製程式碼
可選命名引數
通過 {}
符號,可以用於指定函式引數的名稱。
void enableFlags({bool bold = false, bool hidden = false, @required String content}) {
// ...
}
複製程式碼
可以看到,Dart 支援我們給引數設定預設值。
呼叫:
enableFlags(bold: true, content: 'required');
enableFlags(bold: true, hidden: false, content: 'required');
複製程式碼
使用 @required
註釋的引數,表示必要的引數,在呼叫的時候你不能遺漏它。
這樣的書寫形式也是被允許的,不使用 :
:
void doStuff(
{List<int> list = const [1, 2, 3],
Map<String, String> gifts = const {
'first': 'paper',
'second': 'cotton',
'third': 'leather'
}}) {
print('list: $list');
print('gifts: $gifts');
}
複製程式碼
可選位置引數
通過 []
符號,可以指定該位置的引數是可選的:
String say(String from, String msg,
[String device = 'carrier pigeon', String mood]) {
var result = '$from says $msg';
if (device != null) {
result = '$result with a $device';
}
if (mood != null) {
result = '$result (in a $mood mood)';
}
return result;
}
assert(say('Bob', 'Howdy') ==
'Bob says Howdy with a carrier pigeon');
複製程式碼
其中引數 device
和 mood
的位置的引數就是可選的,且 device
有預設值。
函式作為變數
正如前面所說,Dart 中的函式是一個 Function 型別的物件,因此它可以被賦值給一個變數。
var say= (str){
print(str);
};
say("hi world");
複製程式碼
函式作為入參
函式作為一個物件,它當然也可以被作為引數傳遞:
void execute(var callback){
callback();
}
execute(()=>print("xxx"))
複製程式碼
函式閉包
Dart 函式的特性,使得它很容易實現閉包:
// 返回一個函式物件
Function makeAdder(num addBy) {
return (num i) => addBy + i;
}
void main() {
// 建立一個 +2 的函式
var add2 = makeAdder(2);
// 建立一個 +4 的函式
var add4 = makeAdder(4);
assert(add2(3) == 5);
assert(add4(3) == 7);
}
複製程式碼
從這個例子中,可以感受到閉包的強大,它相當於定義了一個動態可配置的函式物件。
typedef 關鍵字
Dart 提供了 typedef
關鍵字來定義一種函式格式(具有嚴格的格式檢查),比如:
typedef int Compare(Object a, Object b);
複製程式碼
那麼,這種格式的函式就被定義成了 Compare 型別。實際上和類的定義是類似的概念。
看看這個例子:
Compare test = (Object a, Object b){
return 0;
}
複製程式碼
形如此類的函式,就是 Compare 型別的函式。
當你打算把一個函式賦值給 Compare 型別的變數時,它會嚴格檢查 函式的引數型別 和 返回值型別 是否和 Compare 型別函式 完全對應,不對應的話,編譯就會報錯。