在 Dart 中,所有的項目都是物件 (Object),包括函數 (Functions) 也是物件。我們可以將函數作為另一個函數的回傳值,也可以作為函數的參數。關鍵字 typedef
定義一個名稱供函數回傳以及宣告使用。 typedef
也可稱為函數別名 (Function-alias)。
typedef name(parameters)
typedef Calculator(int x, int y);
Calculator
,參數為 (int x, int y)
add(int x, int y)
以及 subtraction(int x, int y)
int add(int x, int y){
return x + y;
}
int subtraction(int x, int y){
return x - y;
}
typedef
定義好的函數別名上。void main(){
Calculator calculator;
calculator = add;
var result1 = calculator(2,1);
calculator = subtraction;
var result2 = calculator(4, 2);
print(result1);
print(result2);
}
//3
//2
將函數作為物件可以直接指派給某變數,而這個變數的類型就是一個函數帶有兩個輸入參數,只要符合定義,就可以指派,跟基本類型的用法一樣。
如果有另一個函數,他的輸入參數數量不一樣,就沒有辦法指定給 Calculator
int add3(int x, int y, int z){
return x + y + z;
}
void main(){
Calculator calculator;
calculator = add3; //Compilation-error
}
有一個函數 isEquals()
,用來比對兩個數值是否相同,這個函數的回傳值是 bool
,跟前面的例子回傳的 int
不同。
bool isEquals(int x, int y){
return x == y;
}
我們同樣可以將這個函數指定給 Calculator calculator
上。
void main(){
Calculator calculator;
calculator = isEquals;
calculator(1, 1); //true
}
預設 typedef
定義的函數回傳值是 dynamic
,也就是說,任何的物件都可以被回傳。包括 void
那麼,我們要如何定義 typedef
的回傳值呢?
更新一下語法:
typedef return_type function_name(parameters);
將上面的範例改為
typedef int Calculator(int x, int y);
void main(){
Calculator calculator;
calculator = isEquals; //Compilation-Error
}
typedef
可以將函數注入至類別當中範例:
typedef MyFunction = int Function(int, int);
class MyClass{
MyFunction function;
MyClass(this.function);
int call(int x, int y){
return function(x, y);
}
}
void main(){
var myClass = MyClass(add);
myClass(10, 20); //30
}
int add(int x, int y){
return x + y;
}
在 Effective Dart 中,有幾條建議與 typedef
相關。
AVOID defining a one-member abstract class when a simple function will do.
避免定義只包含一個簡單的函數的抽象類別。
將
abstract class Predicate<E> {
bool test(E element);
}
改成
typedef Predicate<E> = bool Function(E element);
DON’T use the legacy typedef syntax.
不要使用舊的typedef
語法
//舊
typedef void F();
//新
typedef F = void Function();
在 Dart 中,所有的項目都是物件,就連函數也不例外, typedef
可以把函數定義成型別,接者就可以當作基本型別的方式來使用。
既然可以當作基本型別使用,那麼當作函數的參數,類別的屬性,都是允許的。