### 異常(Exceptions)
1. ***throw***
* 拋出固定類型的異常
~~~
throw new FormatException('Expected at least 1 section');
~~~
* 拋出任意類型的異常
~~~
throw 'Out of llamas!';
~~~
* 因為拋出異常屬于表達式,可以將throw語句放在=>語句中,或者其它可以出現表達式的地方
~~~
distanceTo(Point other) =>
throw new UnimplementedError();
~~~
2. ***catch***
* 將可能出現異常的代碼放置到try語句中,可以通過 on語句來指定需要捕獲的異常類型,使用catch來處理異常。
~~~
try {
breedMoreLlamas();
} on OutOfLlamasException {
// A specific exception
buyMoreLlamas();
} on Exception catch (e) {
// Anything else that is an exception
print('Unknown exception: $e');
} catch (e, s) {
print('Exception details:\n $e');
print('Stack trace:\n $s');
}
~~~
3. ***rethrow***
* rethrow語句用來處理一個異常,同時希望這個異常能夠被其它調用的部分使用。
~~~
final foo = '';
void misbehave() {
try {
foo = "1";
} catch (e) {
print('2');
rethrow;// 如果不重新拋出異常,main函數中的catch語句執行不到
}
}
void main() {
try {
misbehave();
} catch (e) {
print('3');
}
}
~~~
4. ***finally***
* Dart的finally用來執行那些無論異常是否發生都執行的操作。
~~~
final foo = '';
void misbehave() {
try {
foo = "1";
} catch (e) {
print('2');
}
}
void main() {
try {
misbehave();
} catch (e) {
print('3');
} finally {
print('4'); // 即使沒有rethrow最終都會執行到
}
}
~~~
### 函數 Function
* 以下是一個實現函數的例子:
~~~
bool isNoble(int atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
~~~
1. ***main()函數***
* 每個應用程序都必須有一個頂層main()函數,它可以作為應用程序的入口點。該main()函數返回void并具有List參數的可選參數。
~~~
void main() {
querySelector('#sample_text_id')
..text = 'Click me!'
..onClick.listen(reverseText);
}
~~~
* 級聯符號..允許您在同一個對象上進行一系列操作。除了函數調用之外,還可以訪問同一對象上的字段。這通常會為您節省創建臨時變量的步驟,并允許您編寫更流暢的代碼。
~~~
querySelector('#confirm') // Get an object.
..text = 'Confirm' // Use its members.
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'));
~~~
* 上述例子相對于:
~~~
var button = querySelector('#confirm');
button.text = 'Confirm';
button.classes.add('important');
button.onClick.listen((e) => window.alert('Confirmed!'));
~~~
* 級聯符號也可以嵌套使用。 例如:
~~~
final addressBook = (AddressBookBuilder()
..name = 'jenny'
..email = 'jenny@example.com'
..phone = (PhoneNumberBuilder()
..number = '415-555-0100'
..label = 'home')
.build())
.build();
~~~
* 當返回值是void時不能構建級聯。 例如,以下代碼失敗:
~~~
var sb = StringBuffer();
sb.write('foo') // 返回void
..write('bar'); // 這里會報錯
~~~
* ***注意: 嚴格地說,級聯的..符號不是操作符。它只是Dart語法的一部分。***
2. ***可選參數***
* 可選的命名參數, 定義函數時,使用{param1, param2, …},用于指定命名參數。例如:
~~~
//設置[bold]和[hidden]標志
void enableFlags({bool bold, bool hidden}) {
// ...
}
enableFlags(bold: true, hidden: false);
~~~
* 可選的位置參數,用\[\]它們標記為可選的位置參數:
~~~
String say(String from, String msg, [String device]) {
var result = '$from says $msg';
if (device != null) {
result = '$result with a $device';
}
return result;
}
~~~
* 下面是一個不帶可選參數調用這個函數的例子:
~~~
say('Bob', 'Howdy'); //結果是: Bob says Howdy
~~~
* 下面是用第三個參數調用這個函數的例子:
~~~
say('Bob', 'Howdy', 'smoke signal'); //結果是:Bob says Howdy with a smoke signal
~~~
3. ***默認參數***
* 函數可以使用=為命名參數和位置參數定義默認值。默認值必須是編譯時常量。如果沒有提供默認值,則默認值為null。
* 下面是為命名參數設置默認值的示例:
~~~
// 設置 bold 和 hidden 標記的默認值都為false
void enableFlags2({bool bold = false, bool hidden = false}) {
// ...
}
// 調用的時候:bold will be true; hidden will be false.
enableFlags2(bold: true);
~~~
* 下一個示例顯示如何為位置參數設置默認值:
~~~
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;
}
//調用方式:
say('Bob', 'Howdy'); //結果為:Bob says Howdy with a carrier pigeon;
~~~
* 您還可以將list或map作為默認值傳遞。下面的示例定義一個函數doStuff(),該函數指定列表參數的默認list和gifts參數的默認map。
~~~
// 使用list 或者map設置默認值
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');
}
~~~
4. ***作為一個類對象的功能***
* 您可以將一個函數作為參數傳遞給另一個函數。
~~~
void printElement(int element) {
print(element);
}
var list = [1, 2, 3];
// 把 printElement函數作為一個參數傳遞進來
list.forEach(printElement);
~~~
* 您也可以將一個函數分配給一個變量。
~~~
var loudify = (msg) => '!!! ${msg.toUpperCase()} !!!';
assert(loudify('hello') == '!!! HELLO !!!');
~~~
5. ***匿名函數***
* 大多數函數都能被命名為匿名函數,如 main() 或 printElement()。您還可以創建一個名為匿名函數的無名函數,有時也可以創建lambda或閉包。您可以為變量分配一個匿名函數,例如,您可以從集合中添加或刪除它。
* 一個匿名函數看起來類似于一個命名函數 - 0或更多的參數,在括號之間用逗號和可選類型標注分隔。
* 下面的代碼塊包含函數的主體:
~~~
([[Type] param1[, …]]) {
codeBlock;
};
~~~
* 下面的示例定義了一個具有無類型參數的匿名函數item,該函數被list中的每個item調用,輸出一個字符串,該字符串包含指定索引處的值。
~~~
var list = ['apples', 'bananas', 'oranges'];
list.forEach((item) {
print('${list.indexOf(item)}: $item');
});
~~~
* 如果函數只包含一條語句,可以使用箭頭符號=>來縮短它, 比如上面的例2可以簡寫成:
~~~
list.forEach((item) => print('${list.indexOf(item)}: $item'));
~~~
6. ***返回值***
* 所有函數都返回一個值,如果沒有指定返回值,則語句return null,隱式地附加到函數體。
~~~
foo() {}
assert(foo() == null);
~~~