在Dart語言,函數是物件也是一種叫做Function的型態(type)。因此,Function可以當成變數,也可以當做其他函數的參數;另外亦可把類別(class)的實體(instance)當做函數來呼叫。
建議為每個函數的參數以及回傳值都指定類型。
//定義一個函數 判斷清單對應參數是否為null
bool isNoble(int atomicNumber) {
return list[atomicNumber] != null;
}
對於只有一個表達式的方法,可以選擇使用縮寫語法來定義
//定義一個函數 判斷清單對應參數是否為null 縮寫寫法
bool isNoble(int atomicNumber) => list[atomicNumber] != null;
=> 胖箭頭: 簡寫語法用於僅包含一句表達式的函數。這個語法特別是在將匿名函數作為參數傳遞時非常有用。
且在 => 與 ; 之間的只能是表達式,而非語句。例如你不能將一個 if語句 放在其中,但是可以放置條件表達式(condition ? expr1 : expr2)。
有兩種類型的參數:必需和可選的。
必需的參數在參數列表前面,可選參數則是放置於必需參數的後面。
可選參數分為命名參數和位置參數,可在參數列表中任選其一使用,但兩者不能同時出現在參數列表中。
定義函數時,使用 {param1, param2, …} 來指定命名參數
void enableFlags({bool bold, bool hidden}) {...}
當你呼叫函數時,可以使用 參數名: 參數值 的形式來指定命名參數。:例如:
enableFlags(bold: true, hidden: false);
雖然命名參數是可選參數的一種,但是你仍然可以使用 @required 註解來標識一個命名參數是必須的參數,此時呼叫程式則必須為該參數提供一個值。例如:
const Scrollbar({Key key, @required Widget child})
如果想要使用 Scrollbar 的建構式產生一個 Scrollbar 物件而不提供 child 這個參數,則會導致編譯錯誤。
@required 註解定義在 meta 套件中,可以直接導入 package:meta/meta.dart 使用。
使用 [] 將一系列參數包裹起來作為位置參數:
String say(String from, String msg, [String device]) {
var result = '$from says $msg';
if (device != null) {
result = '$result with a $device';
}
return result;
}
下面是不使用可選參數呼叫say函數的例子
assert(say('Bob', 'Howdy') == 'Bob says Howdy');
下面是使用可選參數呼叫say函數的例子
assert(say('Bob', 'Howdy', 'smoke signal') == 'Bob says Howdy with a smoke signal');
可以用 = 為函數的命名和位置參數定義預設值,預設值必須為編譯時常量,沒有指定預設值的情況下預設值為 null。
void main() {
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');
}
List 或 Map 同樣也可以作為預設值。下面的範例定義了一個 doStuff() 的函數,其中的參數 list 和 gifts 指定了一個 List 類型的值和 Map 類型的值。
void main() {
var list1 = [4,5,6];
var map1 = {'first':'one','second':'two','third':'three'};
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');
}
doStuff();
doStuff(list:list1,gifts: map1);
}
綜合範例
引用 IT人
//num a, num b, num c, num d 最普通的傳參: 呼叫時,引數個數和引數順序必須固定
add1(num a, num b, num c, num d) {
print(a + b + c + d);
}
//[num a, num b, num c, num d]傳參: 呼叫時,引數個數不固定,但是引數順序需要一一對應, 不支援命名引數
add2([num a, num b, num c, num d]) {
print(a + b + c + d);
}
//{num a, num b, num c, num d}傳參: 呼叫時,引數個數不固定,引數順序也可以不固定,支援命名引數,也叫可選引數,是dart中的一大特性,這就是為啥Flutter程式碼那麼多可選屬性,大量使用可選引數
add3({num a, num b, num c, num d}) {
print(a + b + c + d);
}
//num a, num b, {num c, num d}傳參: 呼叫時,a,b引數個數固定順序固定,c,d引數個數和順序也可以不固定
add4(num a, num b, {num c, num d}) {
print(a + b + c + d);
}
main() {
add1(100, 100, 100, 100); //最普通的傳參: 呼叫時,引數個數和引數順序必須固定
add2(100, 100); //呼叫時,引數個數不固定,但是引數順序需要一一對應, 不支援命名引數(也就意味著順序不變)
add3(
b: 200,
a: 200,
c: 100,
d: 100); //呼叫時,引數個數不固定,引數順序也可以不固定,支援命名引數(也就意味著順序可變)
add4(100, 100, d: 100, c: 100); //呼叫時,a,b引數個數固定順序篤定,c,d引數個數和順序也可以不固定
}
add3({num a, num b, num c, num d = 100}) {//d就是預設值引數,給的預設值是100
print(a + b + c + d); //1200
}
main() {
add3(b: 200, a: 100, c: 800);
}
main() {
Function square = (a) {
return a * a;
};
Function square2 = (a) {
return a * a * a;
};
print(add(3, 4, square, square2)); //9+64=73
}
num add(num a, num b, [Function op, Function op2]) {
//函式作為引數傳遞
return op(a) + op2(b);
}
每個程式都必須有一個 main() 函數作為入口,main() 函數回傳值為 void 並且有一個 List <String
> 類型的可選參數。
void main(List<String> arguments) {
print(arguments);
print(arguments.length);
print(arguments[1]);
}
沒有名字的函數,稱之為 匿名函數,或 Lambda表達式 或 Closure閉包。
你可以將一個變數設為匿名函數,然後使用它,亦可將該變數添加到集合或從中刪除。
匿名函數看起來與命名函數類似,在括號之間可以定義參數,參數之間用逗號分割;後面大括號中的內容則為函數體:
([[類型] 參數[, …]]) {
函數體;
};
void main() {
var loudify = (msg) => '!!! ${msg.toUpperCase()} !!!';
print(loudify('hello')); //!!! HELLO !!!
}
void main() {
var list = ['apples', 'bananas', 'oranges'];
list.forEach((item) {
print('${list.indexOf(item)}: $item');
});
}
函數可以封閉定義到它範疇(scope)內的變數。接下來的範例中,函數 makeAdder() 設定了變數 addBy。無論函數在什麼時候return,它都可以使用設定的 addBy 變數。
Function makeAdder(int addBy) {
return (int i) => addBy + i;
}
void main() {
// 生成加 2 的函数。
var add2 = makeAdder(2);
// 生成加 4 的函数。
var add4 = makeAdder(4);
print(add2(3)); //5
print(add4(3)); //7
}