Functions——Dart
Dart是一個完全面向對象的語言,它的方法也是對象,對應的類型為Function。
這意味着方法也能被指派給變量,或者當做參數傳遞給其他方法。
下面是一個方法的的示例:
bool isNoble(int atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
函數參數
- 可選命名參數
- 可選位置參數
- 參數預設值
具體請看Functions Paramaters——Dart
main()方法
每個app都必須有一個頂級的main()方法來作為app的入口。main()方法的傳回值為
void
類型,方法參數為
List<String>
的可選參數。
下面的main方法可以接受指令行攜帶過來的參數:
// Run the app like this: dart args.dart 1 test
void main(List<String> arguments) {
print(arguments);
assert(arguments.length == 2);
assert(int.parse(arguments[0]) == 1);
assert(arguments[1] == 'test');
}
你可以使用args library
函數作為一等公民
函數可以作為參數傳遞給另一個函數。
例如:
void printElement(int element) {
print(element);
}
main(){
var list = [1, 2, 3];
// Pass printElement as a parameter.
list.forEach(printElement);
}
output:
1
2
3
将函數指派給一個變量
var loudify = (msg) => '!!! ${msg.toUpperCase()} !!!';
assert(loudify('hello') == '!!! HELLO !!!');
這裡使用了匿名方法。
匿名方法
大多數方法都會被命名,比如說
main()
和
printElement()
。你也可以建立沒有名字的方法,我們稱之為匿名函數;還可以建立lambda表達式或者閉包。
你也可以将匿名函數指派給一本變量,例如你将這個變量從集合中添加或者移除。
匿名方法的參數跟正常方法類似——0或多個參數,由逗号分隔,可選的類型注解,在一對圓括号内部。
下面的代碼塊包含了方法體:
([[Type] param1[, …]]) {
codeBlock;
};
下面的示例定義了一個包含無類型參數item的匿名方法。這個方法被list中的每個item調用,會根據角标擷取item的值,然後列印出對應的String。
var list = ['apples', 'bananas', 'oranges'];
list.forEach((item) {
print('${list.indexOf(item)}: $item');
});
output:
0: apples
1: bananas
2: oranges
使用箭頭表達式簡寫
如果匿名方法的方法體中隻包含一行表達式,這時可以使用箭頭表達式來簡化。
var list = ['apples', 'bananas', 'oranges'];
list.forEach((item) => print('${list.indexOf(item)}: $item'));
output:
0: apples
1: bananas
2: oranges
Lexical scope——作用域
Dart語言支援作用域,這意味着變量的作用域是由代碼所處的位置靜态決定的。
你可以根據方法體的花括号來判斷變量是否在作用域内部。
bool topLevel = true;
void main() {
var insideMain = true;
void myFunction() {
var insideFunction = true;
void nestedFunction() {
var insideNestedFunction = true;
assert(topLevel);
assert(insideMain);
assert(insideFunction);
assert(insideNestedFunction);
}
}
}
現在最内層的nestedFunction方法可以調用外部各個層級的變量,包括頂級的成員變量。
Lexical closures——閉包
閉包是一個可以通路自己的作用域變量的函數對象,甚至閉包當原始作用域的外部使用時也可以。
閉包的概念參考學習Javascript閉包(Closure)——阮一峰
在下面例子中,
makeAdder()
方法捕獲了變量
addBy
,不管傳回的方法如何,它已經記錄下了
addBy
。
/// Returns a function that adds [addBy] to the
/// function's argument.
Function makeAdder(num addBy){
abc(num i){
return addBy + i;
}
return abc;
}
void main() {
// Create a function that adds 2.
var add2 = makeAdder(2);
// Create a function that adds 4.
var add4 = makeAdder(4);
assert(add2(3) == 5);
assert(add4(3) == 7);
}
注意,這裡的閉包方法可以進行簡寫,比如省略傳回值:
makeAdder(num addBy){
abc(num i){
return addBy + i;
}
return abc;
}
内部方法可以使用匿名方法代替:
Function makeAdder(num addBy) {
return (num i) => addBy + i;
}
當然,方法的傳回值也可以省略
makeAdder(num addBy) {
return (num i) => addBy + i;
}
測試方法的一緻性
下面這個例子測試了頂級方法、靜态方法和執行個體方法的一緻性。
void foo() {} // A top-level function
class A {
static void bar() {} // A static method
void baz() {} // An instance method
}
void main() {
var x;
// Comparing top-level functions.
x = foo;
assert(foo == x);// true
// Comparing static methods.
x = A.bar;
assert(A.bar == x);// true
// Comparing instance methods.
var v = A(); // Instance #1 of A
var w = A(); // Instance #2 of A
var y = w;
x = w.baz;
// These closures refer to the same instance (#2),
// so they're equal.
assert(y.baz == x);// true
// These closures refer to different instances,
// so they're unequal.
assert(v.baz != w.baz);// true
}
傳回值
所有非void方法都有傳回值。如果沒有指定傳回值,則方法體的末尾會隐式地添加一句
return null;
。
foo() {}
void baz() {}
main() {
assert(foo() == null);
// assert(baz() == null);// 編譯期異常
}
參考:
https://www.dartlang.org/guides/language/language-tour#functions