dart常用的控制流语句有以下几个:
-
if
和else
-
for
循环 -
while
和do-while
循环 -
break
和continue
-
switch
和case
assert
你也可以使用try-catch
和throw
,这个会在异常篇解释。
if和else
dart的if和else和java完全一致,判断式只能使用boolean值,不像php或者js那样可以用0和1之类的判断。
if (isRaining()) {
you.bringRainCoat();
} else if (isSnowing()) {
you.wearJacket();
} else {
car.putTopDown();
}
for循环
for循环和java一样:
var callbacks = [];
for (var i = 0; i < 2; i++) {
callbacks.add(() => print(i));
}
callbacks.forEach((c) => c());
这避免了js中常见的代码陷阱,这段代码在dart或者像java的语言中输出会是0和1,而在js中输出则是2和2.
dart中的Iterable
和java8的Iterable接口一样都含有forEach
方法用来提供lambda进行内部循环,简化代码:
candidates.forEach((candidate) => candidate.interview());
Iterable
类型例如List
和Set
同样支持for-in
循环:
var collection = [0, 1, 2];
for (var x in collection) {
print(x); // 0 1 2
}
While和do-while
这个和其他语言相通。
Break和continue
使用break
终止循环:
while (true) {
if (shutDownRequested()) break;
processIncomingRequests();
}
使用continue
来跳过当前循环:
for (int i = 0; i < candidates.length; i++) {
var candidate = candidates[i];
if (candidate.yearsExperience < 5) {
continue;
}
candidate.interview();
}
当你使用Iterable
的foreach
方法时你需要使用相应的跳过操作符来跳过循环:
candidates
.where((c) => c.yearsExperience >= 5)
.forEach((c) => c.interview());
这里其实就类似RxJava或者RxJs那样了,你也可以理解为Java8的流或者Kotlin的序列。至于这里的执行原理,文档中并未详述。
Switch和case
Switch可以用来比较数字,字符串等编译时常量(也就是可以用const修饰的)。它使用==
运算符来比较是否相等。被比较的对象必须是相同类的对象,不能是任何它的子类,并且不能重写==
运算符。枚举类型在Switch语句中运行的很优雅。
每个case
子句通常被break
结束,你也可以使用continue
, throw
或者return
语句。使用default
来执行没有case
匹配的情况:
var command = 'OPEN';
switch (command) {
case 'CLOSED':
executeClosed();
break;
case 'PENDING':
executePending();
break;
case 'APPROVED':
executeApproved();
break;
case 'DENIED':
executeDenied();
break;
case 'OPEN':
executeOpen();
break;
default:
executeUnknown();
}
与java类似,case子句如果不加break则会顺序执行后续case子句。
var command = 'CLOSED';
switch (command) {
case 'CLOSED': // Empty case falls through.
case 'NOW_CLOSED':
// Runs for both CLOSED and NOW_CLOSED.
executeNowClosed();
break;
}
dart可以为case添加一个标签,让不同的case之间可以通过continue
关键字跳转:
var command = 'CLOSED';
switch (command) {
case 'CLOSED':
executeClosed();
continue nowClosed;
// Continues executing at the nowClosed label.
case 'OPEN':
print('OPEN');
break;
nowClosed:
case 'NOW_CLOSED':
// Runs for both CLOSED and NOW_CLOSED.
executeNowClosed();
break;
}
这里我开始觉得比较鸡肋,但后来发现这个标签其实是个挺强大的控制方式,他可以实现一个复杂的case流程。读者可以参考Java5之后的枚举状态机模式来推敲这个label的便捷之处,而且其实如果代码比较多的时候整理case子句其实还是挺方便的。
断言Assert
可以使用assert来中断一个出乎意料的执行,这里通常是测试使用,类似Java的单元测试。
// Make sure the variable has a non-null value.
assert(text != null);
// Make sure the value is less than 100.
assert(number < 100);
// Make sure this is an https URL.
assert(urlString.startsWith('https'));
注意:Assert语句在生产环境(就是你打的正式包)中不起作用,它只在开发环境中生效。Flutter在调试模式中开启了断言。
如果想要在断言中添加一句提示信息以供调试可以使用第二个参数:
assert(urlString.startsWith('https'),
'URL ($urlString) should start with "https".');
断言的第一个参数是bool值,如果是true,则继续运行,如果是false,则抛出异常(AssertionError)。