3、函數/方法
3.1、函數也是對象
dart 中函數也是一種對象(類型爲Function
),可以賦值給變量也可以當作參數傳遞給其他函數。
String foo() {
return "foo return";
}
void main() {
var f = foo;
print(f()); // 輸出 foo return
}
3.2、函數可以不指定返回值類型
如果不指定函數的返回值類型,系統將識別爲動態類型(無類型)。
foo() {
return "foo return";
}
String bar() {
return "bar return";
}
void main() {
print(foo.runtimeType); // 輸出 () => dynamic,表示返回值爲 動態類型 的函數
print(bar.runtimeType); // 輸出 () => String,表示返回值爲 String類型 的函數
}
3.3、函數的參數
dart 中函數的參數有必要參數和可選參數之分,且必要參數必須定義在可選參數前。必要參數和其他語言中的方法參數類似。可選參數使用{}
和[]
定義。
使用{}
定義的參數稱爲命名參數,在函數調用時可以不傳參,默認值爲null。但是傳參時必須指定參數名,命名參數也可以爲設爲必須,只需要在參數名前添加required
關鍵字。如下例中的bar
。
使用[]
定義的參數爲可選位置參數,在函數調用時可以不傳參,默認值爲null。如下例中的baz
。
void foo(name, age) {
print("$name is $age.");
}
void bar({required name, age}) {
print("$name is $age.");
}
void baz(name, [age]) {
print("$name is $age.");
}
void main() {
foo("張三", 18); // 輸出 張三 is 18.
foo("張三"); // 報錯,缺少參數 age
bar("李四", 18); // 報錯,命名參數必須指定參數名
bar(name: "李四", age: 18); // 輸出 李四 is 18.
bar(name: "李四"); // 李四 is null.
baz("王五", 18); // 王五 is 18.
baz("王五"); // 王五 is null.
}
命名參數和可選位置參數可以設置默認值,默認值必須是常量值,不可以是變量。
但是必要參數不可以設置默認值(當命名參數標記爲reduired
時也不允許設置默認值)。
void foo(name = "張三", age) { // 報錯,必要參數不能設置默認值
print("$name is $age.");
}
void bar({name = "李四", age}) { // 正確
print("$name is $age.");
}
void baz([name = "王五", age]) { // 正確
print("$name is $age.");
}
3.4、匿名函數
你可以創建一個沒有名字的方法,稱之爲 匿名函數、 Lambda 表達式 或 Closure 閉包。
dart 中匿名函數的格式爲:() {}
。而在 js 中爲:() => {}
,在 java/kotlin 中爲:() -> {}
。
void main() {
const list = ['apples', 'bananas', 'oranges'];
list.forEach((item) {
print('${list.indexOf(item)}: $item'); // 正確, () {} 表示匿名函數
});
list.forEach((item) => {
print('${list.indexOf(item)}: $item'); // 報錯, () => 後只能使用單條語句,不可以使用函數塊
});
list.forEach((item) =>
print('${list.indexOf(item)}: $item') // 正確, () => 使用單條語句
);
}
3.5、返回值
所有未聲明爲void
的函數都有返回值。沒有顯示返回語句的函數最後一行默認爲執行 return null;
。
foo() {}
void bar() {}
void main() {
print(foo.runtimeType); // 輸出 () => dynamic,表示返回值爲 動態類型 的函數
print(foo().runtimeType); // 輸出 null
print(bar.runtimeType); // 輸出 () => void,表示沒有返回值的函數
print(bar().runtimeType); // 報錯,void函數沒有返回值
}
4、運算符
4.1、算數運算符
/
表示除法運算(結果可能含小數),~/
表示除法運算並取整。其他運算符與 java 等大多數語言一致。
print(5 / 2); // 輸出2.5
print(5 ~/ 2); // 輸出2
4.2、類型判斷運算符
as
類型轉換,is
判斷是否是指定類型,is!
判斷是否不是指定類型。
4.3、條件表達式
dart 中的條件表達式條件 ? 表達式1 : 表達式2
可以替代if-else
語句。表達式1 ?? 表達式2
表示當表達式1
不爲null時使用表達式1
,否則使用表達式2
.
String playerName(String? name) => name ?? 'Guest';
// 等價於 條件表達式 的格式
String playerName(String? name) => name != null ? name : 'Guest';
// 等價於 if-else 的格式
String playerName(String? name) {
if (name != null) {
return name;
} else {
return 'Guest';
}
}
4.4及聯運算符
級聯運算符 ..
?..
可以讓你在同一個對象上連續調用多個對象的變量或方法。
var paint = Paint()
..color = Colors.black
..strokeCap = StrokeCap.round
..strokeWidth = 5.0;
// 等價於
var paint = Paint();
paint.color = Colors.black;
paint.strokeCap = StrokeCap.round;
paint.strokeWidth = 5.0;
querySelector('#confirm') // 獲取一個可能爲空的對象
?..text = 'Confirm' // 只需在第一次及聯操作時加null判斷
..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!'));
var sb = StringBuffer();
sb.write('foo')
..write('bar'); // 報錯,因爲此處及聯運算的對象爲 write('foo') 的返回值,而不是StringBuffer()。
// 正確寫法爲
var sb = StringBuffer()
..write('foo')
..write('bar');
4.5、其他運算符
?[]
表示當list不爲null時訪問list的元素。
?.
表示當對象不爲null時訪問對象的成員,與kotlin 的語法類似,es7以上好像也支持了該語法。