先前的範例都是將程式碼寫在 void main(){} 裡面,如果需要處理/運算的步驟很多,在 main() 中會出現很多程式碼,對於維護是相當不容易的,在實務上也不會這麼做。
一般來說,會根據每一個功能建立不同的類 (Class),而在每一個類裡面都有自己的函數。
所以外界需要將類實例化,接者才能呼叫函數。
將程式碼定義在函數內,可以隱藏不必要的實作,外面呼叫時,只需要在意輸入的變數以及輸出的型態。
每一個函數都代表一個特定的任務,可能有回傳值,也有可能有副作用。
void functionName(){
print('This is function');
}
定義一個函數分為四個部分,
套用上方的範例:
回傳類型中的 void ,代表這個函數沒有回傳值,呼叫此函數會得到一個副作用(print)。
可以將上面的範例,以表達式改寫:
改寫方式:將函數本體的大括弧移除,並在前方加上箭頭 (=>)。
void functionName() => print('This is function');
若函數本體只有一行,用表達式可以縮減行數,僅用一行程式碼便看完本體。
函數若有回傳值,使用表達式則可以省略 return 關鍵字。
int function2(){
return 10;
}
//用表達式改寫
int function2() => 10;
定義完函數之後,我們該如何呼叫呢?
輸入函數的名稱加上括弧,則表示呼叫該函數。
void main(){
function1();
var result = function2();
print(result);
}
void functionName() => print('This is function');
int function2() => 10;
好der,我們已經學習如何定義一個函數,並且可以改寫成表達式,但是上面範例中,都沒有任何輸入的參數。
接下來,我將繼續介紹如何定義帶入的參數。
Dart 中,函數有兩種呼叫函數帶入參數的方式,一種是用名稱指定,一種是根據位置帶入。
void printIt(String name, int age){
print("My name is $name, I'm $age.");
}
我們知道,在函數名稱後面的括弧內是定義參數的地方。
參數定義:[Type] [name],並用逗號分隔。
由此得知上面範例,我們定義了兩個參數:
呼叫的時候,就必須要根據參數定義的順序、數量,來逐一傳入,如下
void main(){
printIt('Leo', 30);
}
//My name is Leo, I'm 30
如果順序錯誤,會發生編譯期錯誤。
printIt(30, 'Leo'); //Compilation-error
定義函數時,可以將非必要參數使用中括弧包起來,呼叫函數時,就不一定需要帶入此參數。
void printIt(String name, int age, [String greeting]){
greeting ??= "Hello";
print("$greeting, My name is $name, I'm $age.");
}
void main(){
printIt('Andy', 35, 'Hey');
printIt('Jason', 40);
}
// Hey, My name is Andy, I'm 35.
// Hello, My name is Jason, I'm 40.
我們可以替非必要參數加上預設值。
void printIt(String name, int age, [String greeting = "Hello"]){
print("$greeting, My name is $name, I'm $age.");
}
呼叫函數時,有時候會不清楚輸入的參數是什麼,必須要移動到函數定義查看。
在定義參數時,我們用大括弧將參數包起來。當呼叫函數時,就必須使用名稱來帶入參數,不需要根據其定義的順序。
在呼叫的時候,就可以清楚地知道帶入的參數是什麼用途。
void main(){
printIt(name:'Leo', age:30);
}
void printIt({String name, int age}){
print("My name is $name, I'm $age.");
}
但是,我們有時候是需要命名參數這項功能,不是要讓該參數成為可省略的,我們可以在參數前方加上註解 @required
在參數前方加上 @required ,當呼叫函數卻未帶入該參數時,編譯器會出現警告,如此,就可以避免忘記傳值的情況。
void printIt({@required String name, @required int age}){
print("My name is $name, I'm $age.");
}
我們亦可以在變數後方加上等號指定預設值。
void printIt({ @required String name = "Andy", @required int age = 30 }){
print("My name is $name, I'm $age.");
}
函數,同樣也支援型別推斷,無論是回傳值的型別,或是輸入參數的型別,都可以使用型別推斷,但是使用型別推斷可能會讓函數的可讀性變差,使用時要注意。
printIt(name, age){
print("My name is $name, I'm $age.")
}
函數是程式裡最基本的項目之一,Dart 提供了多種方式傳入參數,如果一個函數只有一個參數,使用位置參數是最合適的,如果有多個參數,可以考慮使用命名參數。那麼,在呼叫函數的時候,
才不會不同檔案切來切去,造成不便。
在使用命名參數時,@required 註解我認為是必要加入的,因為採用命名參數時,這些參數都不是強制輸入,若使用函數的人少傳了一個參數,有可能會造成非預期的動作。加上 @required 可以在使用該函數時減少這類的情況發生。