做者 | 弗拉德
來源 | 弗拉德(公衆號:fulade_me)git
Dart 一樣也是一種面向對象的語音。因此即使函數也是一個對象。類型爲
Function
,這意味着函數可作做爲變量,也也能夠做爲函數的參數。 github
下面是定義一個函數的例子:閉包
isEmpty(List aList) { return aList.length == 0; }
爲了規範其實咱們須要在函數的頭部聲明一下返回值類型,固然若是不聲明也能夠運行,app
bool isEmpty(List aList) { return aList.length == 0; }
若是函數體內只包含一個表達式,你可使用簡寫語法:ide
bool isEmpty(List aList) => aList == 0;
=>
表達的 是 { return 表達式; }
的簡寫,有時=>
也稱之爲胖箭頭語法。函數
函數能夠有兩種形式的參數:必選參數 和 可選參數。必選參數定義在參數列表前面,可選參數必定是定義在必要參數後面。ui
當你調用函數時,可使用 參數名: 參數值 的形式來指定命名參數。例如:this
enableFlags(bold: true, hidden: false);
已命名的參數是可選參數了,除非他們被特別標記爲 required
。code
定義函數時,使用 {param1, param2, …}
來指定命名參數:對象
/// 設置 [bold] 和 [hidden] 標識…… void enableFlags({bool bold, bool hidden}) {...}
雖然命名參數是可選參數的一種類型,可是你仍然可使用 @required
註解來標識一個命名參數是必須的參數,此時調用者則必須爲該參數提供一個值。例如:
const Scrollbar({Key key, @required Widget child})
若是調用者想要經過 Scrollbar
的構造函數構造一個 Scrollbar
對象而不提供 child 參數,則會致使編譯錯誤。
使用 []
將一系列參數包裹起來做爲可選參數:
strings(String s1, String s2, [String s3]) { var result = '$s1 and $s2'; if (s3 != null) { result = '$result and $s3'; } print(result); }
下面是不使用可選參數調用上述函數的示例:
strings("s1", "s2"); s1 and s2
下面是使用可選參數調用上述函數的示例:
strings("s1", "s2", "s3"); s1 and s2 and s3
咱們能夠用 =
爲函數的命名參數和可選參數定義默認值,默認值必須爲編譯時常量,沒有指定默認值的狀況下默認值爲 null
。
下面是設置可選參數默認值示例:
/// 設置 [bold] 和 [hidden] 標識…… void enableFlags({bool bold = false, bool hidden = false}) {...} // bold 的值將爲 true;而 hidden 將爲 false。 enableFlags(bold: true);
下一個示例 默認值:
strings(String s1, String s2, [String s3 = 'this is s3', String s4]) { var result = '$s1 and $s2'; if (s3 != null) { result = '$result and $s3'; } if (s4 != null) { result = '$result and $s4'; } print(result); } strings("s1", "s2"); s1 and s2 and this is s3
每一個 Dart
程序都必須有一個 main()
頂級函數做爲程序的入口,main()
函數返回值爲 void
。
下面是一個 Flutter 應用的 main()
函數示例:
void main() { runApp(MyApp()); }
能夠將函數做爲參數傳遞給另外一個函數。例如:
void printElement(int element) { print(element); } // 將 printElement 函數做爲參數傳遞。 var list = [1, 2, 3]; list.forEach(printElement);
你也能夠將函數賦值給一個變量,好比:
var loudify = (msg) => '!!! ${msg.toUpperCase()} !!!'; var result = loudify('hello'); print(result);
大多數方法都是有名字的,好比
main()
或printElement()
。你能夠建立一個沒有名字的方法,稱之爲 匿名函數,其實匿名函數很常見,也有不一樣的叫法,在C++裏面叫Lambda表達式,在Objective-C叫Block閉包。你能夠將匿名方法賦值給一個變量而後使用它。
匿名方法看起來與命名函數h相似,在括號之間能夠定義參數,參數之間用逗號分割。
後面大括號中的內容則爲函數體:
([[類型] 參數[, …]]) { 函數體; };
下面代碼定義了只有一個參數 item
且沒有參數類型的匿名方法。List
中的每一個元素都會調用這個函數,打印元素位置和值的字符串:
var list = ['apples', 'bananas', 'oranges']; list.forEach((item) { print('${list.indexOf(item)}: $item'); });
若是函數體內只有一行語句,你可使用胖箭頭縮寫法。下面代碼的運行結果,與上面代碼的運行結果是一致的。
list.forEach( (item) => print('${list.indexOf(item)}: $item'));
變量的做用域在寫代碼的時候就肯定了,大括號內定義的變量只能在大括號內訪問,與 Java 相似。
下面是一個嵌套函數中變量在多個做用域中的示例:
bool topLevel = true; void main() { var insideMain = true; void myFunction() { var insideFunction = true; void nestedFunction() { var insideNestedFunction = true; assert(topLevel); assert(insideMain); assert(insideFunction); assert(insideNestedFunction); } } }
注意 nestedFunction()
函數能夠訪問包括頂層變量在內的全部的變量。
返回值
全部的函數都有返回值。沒有顯示返回語句的函數最後一行默認爲執行 return null
;。
foo() {} assert(foo() == null);
本文全部代碼都已上傳到Github