1. 指定返回值得函數
/** * 無返回值的函數 * params: 可以是任意類型(var和Object類型也可以任意類型)。 當然這里的參數類型你可以隨意指定我這里已dynamic為例 * 參數類型:你也可以指定var、Object等,再比如說你可以指定num, int,double, String.... * 如果我們對參數沒有限制的話可以使用這個 */ void printDynamicParams(dynamic params){ print(params); }
主函數中我們調用printDynamicParams函數:
main(List<String> arguments) { printDynamicParams(12.33); printDynamicParams('liyahong'); printDynamicParams("Dart Method test"); printDynamicParams(10); printDynamicParams(true); }
控制台輸出結果:

這里我們可以傳入任意類型,適用於參數類型不固定的情況使用。這里大家可能會有一個疑惑,包括我當時學習的時候也有這個疑惑,既然dynamic、var、Object都可以指定任意類型,那它們有什么區別嗎?下面我們就來說下這個問題。
- (1)var
var是C# 3中引入的,其實它僅僅只是一個語法. var本身並不是一種類型, 其它兩者object和dynamic是類型。var聲明的變量在賦值的那一刻,就已經決定了它是什么類型。
如果你這樣使用,就會有編譯錯誤:
var a = 1; a = "Test";
- (2)Object
object之所以能夠被賦值為任意類型的原因,其實都知道,因為所有的類型都派生自object.
它可以賦值為任何類型:
object a = 1; a = "Test";
- (3)dynamic
dynamic不是在編譯時候確定實際類型的, 而是在運行時。
所以下面的代碼是能夠通過編譯的,但是會在運行時報錯:
dynamic a = "test"; a++;
2. 不指定返回值類型的函數
/** * 我們可以不指定返回值類型,這樣的函數返回值默認為Object,也就是說你可以返回任意類型 * params: 可以是任意類型 */ printReturnObjectParams(Object params){ print(params); return params; }
printObjectParams(Object params){ print(params); }
主函數中我們調用printReturnObjectParams 和 printObjectParams函數:
main(List<String> arguments) { print(printReturnObjectParams("liyahong")); print(printReturnObjectParams(111)); print(printReturnObjectParams(12.36)); print(printObjectParams(true)); printObjectParams('test'); }
控制台輸出結果:

由上面的結果可以看出,如果沒有返回值得時候默認將會返回null。
3.如果你的函數中只有一個表達式,你可以使用快速寫法
/** * 無返回值類型函數的快速寫法 * 注意:這種寫法只適用於無返回值 並且 函數體中僅有一個表達式的函數。 */ void printNumber(num number) => print(number);
主函數中我們調用printNumber函數:
main(List<String> arguments) {
printNumber(123);
printNumber(22.3333);
}
控制台輸出結果:
這里我們提到了num關鍵字,在上篇博客中沒有講到,這里簡單說一下。
我們先看一下官方對它的說法:
/** * An integer or floating-point number. * It is a compile-time error for any type other than [int] or [double] * to attempt to extend or implement num. */ 翻譯: /** * 整數或浮點數。 * 除[int]或[double]之外的任何類型都是編譯時錯誤 * 試圖擴展或實現num。 */
也就是說它是一個數值類型,僅支持int 和 double類型。
4.可選參數
一個函數可以有兩種參數:可選的和必需的,必需參數放在前面,后面跟可選參數
可選參數可以是位置參數或命名參數,兩種都可以有默認值,如果沒有提供默認值則為null。但是這兩種參數不能同時當做可選參數。
- (1)可選的命名參數
定義一個函數,使用 {param1, param2, …} 指定命名參數,調用函數時,你可以指定使用命名參數 paramName: value
無默認值例子:
/** * 沒有默認值 */ void printBool({bool flag, bool action}) => print("flag: " + flag.toString() + "\r\naction: " + action.toString() + "\r\n");
有默認值(命名參數使用“=”指定默認值)例子:
/** * 有默認值 */ void printDefaultBool({bool flag = false}) => print(flag);
主函數中我們調用printBool 和 printDefaultBool函數:
main(List<String> arguments) { printBool(flag: true, action: false); printBool(flag: false); printBool(); printDefaultBool(flag: true); printDefaultBool(); }
控制台輸出結果:
(2)可選的位置參數
把參數用 [ ] 包裝起來,就能標識成位置參數
無默認值例子:
/** * 可選的位置參數 * 無默認值 */ String msg(String msg, [String time]){ if (time != null) { return msg + ' with ' + time; } return msg; }
有默認值(位置參數使用“=”指定默認值)例子:
/** * 可選的位置參數 * 有默認值 */ String msgTwo(String msg, [String time = '2018', String name]){ if (time == null) { return msg + " from " + name; } if (name != null) { return msg + " with " + time + " from " + name; } return msg + " with " + time; }
主函數中我們調用msg 和 msgTwo函數:
print(msg("This is msg content", '2017')); print(msg("Tiis is msg content")); print(msgTwo("This is msgTwo content", '2017', 'liyahong')); print(msgTwo("This is msgTwo content", null, 'liyahong')); print(msgTwo("This is msgTwo content"));
控制台輸出結果:
總結:可選的命名參數的聲明使用“{}”,使用“:”指定默認值,可選的位置函數的聲明使用“[]”,使用“=”指定默認值。
5.關於重載
Dart語言是不支持方法重載( 重載就是方法名相同,參數(個數或類型)不同(稱之為簽名不同))的。這里可能會有人問:“Dart不支持方法重載,那構造函數怎么辦呢?”,雖然Dart它不支持方法的重載,但是它支持命名構造函數,我們通過下面例子學習一下:
class Test{ int x; int y; Test(){} Test.X(int x){ this.x = x; } Test.Y(int y){ this.y = y; } Test.XY(int x, int y){ this.x = x; this.y = y; } @override
String toString() { if (x != null && y != null) { return "x: " + x.toString() + " y: " + y.toString(); } if (x != null) { return "x: " + x.toString(); } if (y != null) { return "y: " + y.toString(); } return super.toString(); } }
我們在主函數中創建Test對象:
main(List<String> arguments) { Test testX = new Test.X(1); print(testX.toString()); Test testY = new Test.Y(2); print(testY.toString()); Test testXY = new Test.XY(3, 4); print(testXY.toString()); }
控制台輸出結果:
具體內容我們后面講解。
6.高級函數
/** * 高級函數 * element 沒有指定參數類型,默認Object任何類型 */ printElement(element){ print(element); }
在主函數中調用printElement函數,這里是將函數作為參數傳入
main(List<String> arguments) { var list = ['張三', '李四', '王麻子']; list.forEach(printElement); }
控制台輸出結果:
將一個函數分配給一個變量
main(List<String> arguments) { var loudify = (msg) => '${msg.toUpperCase()}'; print(loudify('hello')); }
控制台輸出結果:
7.作用域
dart的作用域跟其他語言一樣,直接看一個例子
var test = true; main(List<String> arguments) { var test1 = true;
myFunction(){ var test2 = true;
needFunction(){ var test3 = true; assert(test); assert(test1); assert(test2); assert(test3); } } }
8.閉包
dart的閉包就是函數對象,其實跟JavaScript的閉包函數差不多,理論請參考JavaScript的閉包函數,這里直接寫個例子
//返回一個函數對象,功能是返回累加的數字 Function makeAdder(num addBy) { return (num i) => addBy + i; } main(List<String> arguments) { //創建一個函數add2,add2返回2 var add2 = makeAdder(2); //創建一個函數add4,add4返回4 var add4 = makeAdder(4); //add2返回2+3 assert(add2(3) == 5); //add4返回4+3 assert(add4(3) == 7); }
9.函數是否相等
測試高階函數、靜態方法和實例方法是否相等
//一個高階函數 foo() {} class SomeClass { //一個靜態方法 static void bar() {} //一個實例方法 void baz() {} } main(List<String> arguments) { var x; //比較高階函數 x = foo; assert(foo == x); //比較靜態方法 x = SomeClass.bar; assert(SomeClass.bar == x); //比較實例方法 var v = new SomeClass(); var w = new SomeClass(); var y = w; x = w.baz; assert(y.baz == x); assert(v.baz != w.baz); }
