認識 Dart function 的參數: positional parameters、optional positional parameters、named parameters、required named parameters

定義 Dart function 時,我們可以宣告四種類型的參數,positional parameters、optional positional parameters、named parameters、required named parameters,以下我們逐一介紹它們的語法、特性和差異。

  • positional parameters (必填的位置參數)。
  • 使用 [ ] 宣告 optional positional parameters(可省略的位置參數)。
  • 使用 { } 宣告 named parameters(可省略的命名參數)。
  • 使用 required 宣告 named parameters。(必填的命名參數)
  • 混搭 positional parameters、optional positional parameters 和 named parameters。
  • 比較表。

ps: 可從 DartPad 練習以下的程式範例。

positional parameters (必填的位置參數)

positional parameters 是最基本的參數寫法,直接在 function 的 ( ) 裡宣告參數的型別和名字,就像 function add 的 number1 和 number2。

void main() {
var sum = add(10, 20);
print(sum);
}

int add(int number1, int number2) {
return number1 + number2;
}

結果

30

傳入 positional parameters 的內容時,有以下幾點要注意的地方。

  • 要照順序傳入。

add(10, 20) 為例,10 對應 number1,20 對應 number2。

  • positional parameters 不可省略。
void main() {
var sum = add(10);
print(sum);
}

int add(int number1, int number2) {
return number1 + number2;
}

add(10) 只傳入 1 個參數,應該要傳入 2 個,錯誤訊息如下。

Error: Too few positional arguments: 2 required, 1 given.
var sum = add(10);

使用 [ ] 宣告 optional positional parameters(可省略的位置參數)

如果希望剛剛照順序傳入的參數可省略,我們可宣告 optional positional parameters。

只要將參數包在 [ ] 裡,即可讓它變成 optional positional parameters。既然參數可省略,表示參數應該要有預設值或型別為 nullable,如此省略時 Dart 才能知道參數的內容。

以下我們分別說明有預設值或型別為 nullable 的寫法。

  • 有預設值的 optional positional parameters。

number1 = 1 將 number1 預設為 1,number2 = 2 將 number2 預設為 2。

void main() {
var sum = add(10, 20);
print('add(10, 20) = $sum');
sum = add();
print('add() = $sum');
sum = add(10);
print('add(10) = $sum');
}

int add([int number1 = 1, int number2 = 2]) {
return number1 + number2;
}

結果。

add(10, 20) = 30
add() = 3
add(10) = 12

add(10) 的結果為 12,因為參數要照順序傳入,因此 10 對應 number1,number2 採用預設值 2。

值得注意的,當 positional parameters 沒有加 [ ],呼叫 function 時一定要傳入參數的內容,因此它設定預設值完全無意義。

int add(int number1 = 1, int number2 = 2) {
return number1 + number2;
}

以上程式將產生錯誤。

Error: Non-optional parameters can't have a default value.
int add(int number1 = 1, int number2 = 2) {
  • 型別為 nullable 的 optional positional parameters。
void main() {
var sum = add(10, 20);
print('add(10, 20) = $sum');
sum = add(10);
print('add(10) = $sum');
sum = add();
print('add() = $sum');
}

int add([int? number1, int? number2]) {
if (number1 != null && number2 != null) {
return number1 + number2;
} else if (number1 != null) {
return number1;
} else {
return 0;
}
}

結果。

因為參數要照順序傳入,所以如果只有傳一個數字時,它一定是 number1,不會是 number2。

add(10, 20) = 30
add(10) = 10
add() = 0

使用 { } 宣告 named parameters(可省略的命名參數)

我們可用 { } 定義 named parameter,它將帶來以下幾個好處。

  • 傳入 named parameter 的內容時必須寫出參數的名字,它將讓程式的可讀性更好,一眼看出參數的意思。
  • 可用任意的順序傳入 named parameter,不用再怕順序寫錯。
  • name parameter 可省略。既然參數可省略,表示參數應該要有預設值或型別為 nullable,如此省略時 Dart 才能知道參數的內容。

以下我們改寫剛剛的例子說明。

  • 有預設值的 named parameters。
void main() {
var sum = add(number1: 10, number2: 20);
print('add(number1: 10, number2: 20) = $sum');
sum = add(number2: 20, number1: 10);
print('add(number2: 20, number1: 10) = $sum');
sum = add(number1: 10);
print('add(number1: 10) = $sum');
sum = add(number2: 20);
print('add(number2: 20) = $sum');
sum = add();
print('add() = $sum');
}

int add({int number1 = 1, int number2 = 2}) {
return number1 + number2;
}

結果。

add(number1: 10, number2: 20) = 30
add(number2: 20, number1: 10) = 30
add(number1: 10) = 12
add(number2: 20) = 21
add() = 3

說明。

  1. 傳入 named parameter 的內容時必須寫出參數的名字。

格式為參數名字,冒號和內容,因此 add(number1: 10, number2: 20) 表示 number1 的內容為 10,number2 的內容為 20。

沒有寫參數名字將出現錯誤,比方以下程式將讓 Dart 誤會,它會認為 10 和 20 是 positional arguments。

var sum = add(10, 20);

2. 可用任意的順序傳入 named parameter。

由於有名字,我們用任意的順序傳入參數,不用再怕順序寫錯,add(number2: 20, number1: 10) 也是可以的。

  • 型別為 nullable 的 named parameters。
void main() {
var sum = add(number1: 10, number2: 20);
print('add(number1: 10, number2: 20) = $sum');
sum = add(number2: 20, number1: 10);
print('add(number2: 20, number1: 10) = $sum');
sum = add(number1: 10);
print('add(number1: 10) = $sum');
sum = add(number2: 20);
print('add(number2: 20) = $sum');
sum = add();
print('add() = $sum');
}

int add({int? number1, int? number2}) {
if (number1 != null && number2 != null) {
return number1 + number2;
} else if (number1 != null) {
return number1;
} else if (number2 != null) {
return number2;
} else {
return 0;
}
}

結果。

add(number1: 10, number2: 20) = 30
add(number2: 20, number1: 10) = 30
add(number1: 10) = 10
add(number2: 20) = 20
add() = 0

使用 required 宣告 named parameters(必填的命名參數)

如果想要 name parameter 不可省略,則可在參數前加上 required。由於參數不可省略,因此我們也不能設定預設值。不過型別設為 nullable 倒是可以,因為呼叫時可傳入 null。

void main() {
var sum = add(number1: 10, number2: 20);
print('add(number1: 10, number2: 20) = $sum');
sum = add(number2: 20, number1: 10);
print('add(number2: 20, number1: 10) = $sum');
}

int add({required int number1, required int number2}) {
return number1 + number2;
}

結果。

add(number1: 10, number2: 20) = 30
add(number2: 20, number1: 10) = 30

number1 和 number2 加了 required,因此呼叫 add 時一定要傳入 number1 和 number2 的內容。

以下程式少傳了 number2,因此會出現錯誤。

var sum = add(number1: 10);

錯誤訊息如下。

Error: Required named parameter 'number2' must be provided.
var sum = add(number1: 10);

值得注意的,required 會讓 named parameters 成為必填的參數,因此定義 function 時設定參數的預設值不再有意義。

int add({required int number1 = 1, required int number2}) {
return number1 + number2;
}

以上寫法將出現錯誤訊息。

Error: Named parameter 'number1' is required and can't have a default value.
int add({required int number1 = 1, required int number2}) {

混搭 positional parameters、optional positional parameters 和 named parameters

定義 function 時我們也可混搭多種類型的參數,不過不能同時包含 optional positional parameters 和 named parameters,因此混搭只有以下兩種可能。

  • positional parameters 和 optional positional parameters。
  • positional parameters 和 named parameters。

為了讓 Dart 正確判斷傳入的參數,function 定義時 positional parameters 要寫在前面,optional positional parameters 或 named parameters 要寫在後面。

以下我們分別舉例說明。

  • positional parameters 和 optional positional parameters。
void main() {
var sum = add(10, 20);
print('add(10, 20) = $sum');
sum = add(10);
print('add(10) = $sum');
}

int add(int number1, [int number2 = 2]) {
return number1 + number2;
}

結果。

add(10, 20) = 30
add(10) = 12

add(10) 為例,因為 positional parameter number1 寫在前面,Dart 才知道 10 是 number1,省略的是 number2。

若是順序顛倒將出現錯誤,比方以下程式將 optional positional parameters 寫在前面,positional parameters 寫在後面。

int add([int number1 = 1], int number2) {
return number1 + number2;
}
  • positional parameters 和 named parameters。

呼叫時 named parameters 可照任意順序傳入,因此 add(10, number2: 20)add(number2: 20, 10) 都是 ok 的。

void main() {
var sum = add(10, number2: 20);
print('add(10, number2: 20) = $sum');
sum = add(number2: 20, 10);
print('add(number2: 20, 10) = $sum');
sum = add(10);
print('add(10) = $sum');
}

int add(int number1, {int number2 = 2}) {
return number1 + number2;
}

結果。

add(10, number2: 20) = 30
add(number2: 20, 10) = 30
add(10) = 12

比較表

參考連結

--

--

彼得潘的 iOS App Neverland
彼得潘的 Flutter App 開發問題解答集

彼得潘的iOS App程式設計入門,文組生的iOS App程式設計入門講師,彼得潘的 Swift 程式設計入門,App程式設計入門作者,http://apppeterpan.strikingly.com