流程控制在大部分语言中大同小异,在Dart中只有最后一个assert比较特殊。

常用流程控制

  • if 和 else
  • for循环
  • while和do-while循环
  • break和continue
  • switch和case
  • assert

if 和 else

与JavaScript不同的是,条件必须使用布尔值,不允许其他值。

For循环

  1. // 基本For循环
  2. var message = StringBuffer('Dart is fun');
  3. for (var i = 0; i < 5; i++) {
  4. message.write('!');
  5. }
  6. // Dart for循环内部的闭包捕获了索引的值,避免了JavaScript中常见的陷阱。例如:
  7. var callbacks = [];
  8. for (var i = 0; i < 2; i++) {
  9. callbacks.add(() => print(i));
  10. }
  11. callbacks.forEach((c) => c());

While 和 do-while 循环

  1. // while循环在循环之前先检验条件是否为真
  2. while (!isDone()) {
  3. doSomething();
  4. }
  5. // do-while循环在一次循环结束之后检查条件是否为真
  6. do {
  7. printLine();
  8. } while (!atEndOfPage());
  9. // 所以使用while和do-while要非常小心,因为使用do-while如果条件为假也会至少执行一次循环体中的语句。

Break 和 continue

  1. // 使用break终止循环:
  2. while (true) {
  3. if (shutDownRequested()) break;
  4. processIncomingRequests();
  5. }
  6. // 使用continue跳出本次循环继续下次循环:
  7. for (int i = 0; i < candidates.length; i++) {
  8. var candidate = candidates[i];
  9. if (candidate.yearsExperience < 5) {
  10. continue;
  11. }
  12. candidate.interview();
  13. }

可迭代的循环

  1. // 如果你使用的是可迭代的,比如列表或集合,你可能会用不同的方式来写这个例子:
  2. candidates
  3. .where((c) => c.yearsExperience >= 5)
  4. .forEach((c) => c.interview());
  5. class A {
  6. var yearsExperience;
  7. A(int year)
  8. {
  9. this.yearsExperience = year;
  10. }
  11. interview() {
  12. print(this.yearsExperience);
  13. }
  14. }
  15. void main() {
  16. List personList = [
  17. A(1),
  18. A(2),
  19. A(5),
  20. A(6)
  21. ];
  22. ///第一种写法
  23. for(int i = 0; i < personList.length; i++) {
  24. var person = personList[i];
  25. if (person.yearsExperience < 5) {
  26. continue;
  27. }
  28. person.interview();
  29. }
  30. ///第二种写法
  31. personList
  32. .where((c) => c.yearsExperience >= 5)
  33. .forEach((c) => c.interview());
  34. }

两次结果都相同,那么这儿的where()方法究竟是什么呢,我们在后续会接触到,他是dart.core中的iterable.dart中的方法,他返回复合where()中条件的集合视图,所以在where()后边我们可以继续调用forEach(),当然如果where()返回的集合视图为空也不会出现错误,仅仅是forEach()不执行而已。这儿where()的作用类似于过滤器。

switch 和 case

在Dart中switch语句使用 “”运算来比较整数,字符串或者编译时常量。被比较对象必须都是同一个类的实例(而不是它的任何子类型),并且这个类不能重写“”操作。枚举类型在switch语句是一种非常好的应用场景。

注意:Dart中的Switch语句适用于有限的情况,例如在解释器或扫描器中。

switch的规则是每个非空的case子句以一个break语句结束。结束非空case子句的其他有效方法是continue、throw或return语句。

当没有case子句匹配时,使用default子句执行代码:

  1. var command = 'OPEN';
  2. switch (command) {
  3. case 'CLOSED':
  4. executeClosed();
  5. break;
  6. case 'PENDING':
  7. executePending();
  8. break;
  9. case 'APPROVED':
  10. executeApproved();
  11. break;
  12. case 'DENIED':
  13. executeDenied();
  14. break;
  15. case 'OPEN':
  16. executeOpen();
  17. break;
  18. default:
  19. executeUnknown();
  20. }

下面的示例省略了case子句中的break语句,从而产生错误:

  1. var command = 'OPEN';
  2. switch (command) {
  3. case 'OPEN':
  4. executeOpen();
  5. // ERROR: Missing break
  6. case 'CLOSED':
  7. executeClosed();
  8. break;
  9. }

然而,Dart支持空的case子句,支持fall-through的格式:

  1. var command = 'CLOSED';
  2. switch (command) {
  3. case 'CLOSED': // Empty case falls through.
  4. case 'NOW_CLOSED':
  5. // 无论command是CLOSED还是NOW_CLOSED都执行
  6. executeNowClosed();
  7. break;
  8. }

如果你真的需要使用fall-through格式,你可以使用continue语句和一个标签,例如:

  1. var command = 'CLOSED';
  2. switch (command) {
  3. case 'CLOSED':
  4. executeClosed();
  5. continue nowClosed;
  6. // Continues executing at the nowClosed label.
  7. nowClosed:
  8. case 'NOW_CLOSED':
  9. // Runs for both CLOSED and NOW_CLOSED.
  10. executeNowClosed();
  11. break;
  12. }

case子句可以有局部变量,只能在该子句的范围内可见。

Assert (断言)

如果布尔条件为false,则使用assert语句中断正常执行。

Assert语句不会影响生产环境中代码的执行,它仅仅在测试环境中起作用。在Flutter的调试模式下可以使用assert。默认情况下,像(dartdevc typically)只支持开发环境的工具默认支持assert。例如dart和dart2js通过命令行标记:—enable-asserts来支持asserts。

要将提示消息附加到断言,请添加一个字符串作为第二个参数。

  1. assert(urlString.startsWith('https'),
  2. 'URL ($urlString) should start with "https".');

断言的第一个参数可以是任何解析为布尔值的表达式。如果表达式的值为true,则断言成功并继续执行。如果是false,则断言失败,并抛出异常(AssertionError)。