赋值运算符
- = 普通赋值
- ??= 当变量值为null的时候才赋值
void main() {
var a = 10;
var b;
b ??= 5;
print(b);
var c = 20;
c ??= 5;
print(c);
}
打印结果为:
5
20
上面代码中,b一开始并没有赋值,为null,此时使用??=赋值会生效,所以打印b的值为5;c由于已经赋值了,不为null,故??=不生效,c的值还是20。
条件表达式
- 三目运算符:condition ? expr1 : expr2
- ??运算符: expr1 ?? expr2 当expr1为null的时候,就会使用expr2
void main() {
int gender = 0;
var str = gender == 0 ? "Male" : "Female";
print(str);
var a;
var b = "Dart";
print(a ?? b); //如果a为null则使用b的值
a = "Java";
print(a ?? b);//如果a为null则使用b的值
}
打印结果为:
Male
Dart
Java
控制语句
Dart的控制语句和Java的控制语句几乎是一样的,这里就简单介绍下。
条件语句
- if语句
- if...else 语句
- if...else if...else语句
for语句
格式为:
for(赋初值;判断条件;赋值加减){
}
如:
for (var i = 0; i <= 5; i++) {
}
格式为:
for(element in list){
}
如:
var list = [1,2,3];
for(var item in list){
}
while循环
- while循环
- do...while循环
break和continue
switch case
方法
方法的定义
返回类型 方法名(参数1,参数2, ...){
方法体...
return 返回值
}
如:
int getArea(int width, int height){
return width * height;
}
方法的特性
- 方法也是对象,并且有具体类型Function
- 返回值类型、参数类型都可省略
- 箭头语法:=>expr 是 {return expr;}缩写,只适用于一个表达式
- 方法都有返回值。如果没有指定,默认return null
上述定义求面积的方法,getArea()可以定义为如下几种:
- 省略返回值类型
getArea(int width, int height){
return width * height;
}
- 省略参数类型
int getArea(width, height){
return width * height;
}
- 省略返回值类型和参数类型
getArea(width, height){
return width * height;
}
- 箭头语法
getArea(width, height) => width * height;
打印返回值为void的方法:
void main() {
print(printPerson("黄家驹", 31));
}
printPerson(name,age){
print("name = $name, age= $age");
}
打印结果为:
name = 黄家驹, age= 31
null
可选参数
- 可选命名参数:{params1, params2, ...}
- 可选位置参数: [params1, params2, ...]
可选命名参数可以根据指定参数名传入对应参数,不需要根据该参数的位置来传,而可选位置参数只能按照参数所在的位置按顺序传入。
可选命名参数演示:
void main() {
printPerson("黄家驹");
printPerson("黄家驹", age: 31);
printPerson("黄家驹", gender: "Male");
printPerson("黄家驹", age: 31, gender: "Male");
}
printPerson(String name, {int age, String gender}){
print("name = $name, age= $age, gender=$gender");
}
可以看到可选命名参数可传可不传,如果要传入可选命名参数,则需要指定参数名传入
可选位置参数演示:
void main() {
printPerson2("黄家驹");
printPerson2("黄家驹", 31);
printPerson2("黄家驹", 31, "Male");
}
printPerson2(String name, [int age, String gender]){
print("name = $name, age= $age, gender=$gender");
}
可以看到可选位置参数可传可不传,如果要传入则需要按照顺序传入
默认参数
- 使用 = 在可选参数指定默认值
- 默认值只能是编译时常量
void main() {
printPerson("黄家驹");
printPerson("黄家驹", age: 58);
printPerson("黄家驹", age: 58, gender: "Male");
}
printPerson(String name, {int age = 31, String gender = "Male"}){
print("name = $name, age= $age, gender=$gender");
}
打印结果为:
name = 黄家驹, age= 31, gender=Male
name = 黄家驹, age= 58, gender=Male
name = 黄家驹, age= 58, gender=Male
上述代码中printPerson()方法中的可选参数age指定默认值为31,gender指定默认值为"Male"当没传入age时,则会使用默认的31,没传入gender时,会使用默认的"Male"。
方法对象
- 方法可作为对象赋值给其他变量
void main() {
var func = printHello;
func();
}
printHello(){
print("Hello");
}
可以看到printHello()方法可以作为对象赋值给变量func,func要执行的话只需要将其作为方法调用即可。
- 方法可作为参数传递给其他方法
上章演示List的forEach()方法时,可能会有疑问,为何传入一个print即可遍历打印出list的元素,到这里应该疑惑尽释了,查看forEach源码可以看到:
void forEach(void f(E element)) {
for (E element in this) f(element);
}
forEach接收的是一个void方法,而print方法可以作为参数传入,然后遍历list逐个调用print打印当前元素。
匿名方法
- 可赋值给变量,通过变量进行调用
void main() {
var hello = (){print("Hello");};
hello();
}
可以看到直接将一个打印"Hello"的匿名方法直接赋值给了hello变量,然后将其作为方法调用即可。
上述也可以写成:
((){print("Hello");})();
但是不推荐使用,因为这种方法没有名称直接调用,不便于理解。
- 可在其他方法中直接调用或传递给其他方法
和上述演示方法作为参数传入相似:
void main() {
var list = ["1","2","3"];
list.forEach((item){print(item * 3);});
}
这里调用list的forEach()方法时,传入了一个匿名方法,将遍历到的每个元素重复拼接3次打印,打印的结果为:
111
222
333
闭包
- 闭包是一个方法(对象)
- 闭包定义在其他方法内部
- 闭包能够访问外部方法内的局部变量,并持有其状态
void main() {
var func = a();
func();
func();
func();
}
a(){
int count = 0;
printCount(){
print(count++);
}
return printCount;
}
在a()方法中声明一个闭包printCount,并将其暴露出去,通过变量func接收a()方法,并进行多次调用,打印结果为:
0
1
2
可以看到count的值依次递增,说明闭包能访问外部方法内的局部变量和持有其状态。
也可以使用匿名方法的方式返回闭包:
a(){
int count = 0;
return (){
print(count++);
};
}