Dart 简明教程 - 04 - Control flow statements

496 阅读4分钟

本系列教程大多翻译自 Dart 官网,因本人英语水平有限,可能有些地方翻译不准确,还请各位大佬斧正。如需转载请标明出处,谢绝 CSDN 爬虫党。

流程控制语句(Control flow statements)

你可以在 Dart 中使用下列代码去控制流程:

  • ifelse
  • for 循环
  • whiledo-while 循环
  • breakcontinue
  • switchcase
  • assert

你也可以使用 try-catchthrow 来处理异常。

if & else

Dart 支持 if 语句和可选的 else 语句:

if (isRaining()) {
  you.bringRainCoat();
} else if (isSnowing()) {
  you.wearJacket();
} else {
  car.putTopDown();
}

和 JavaScript 不同的是,判断条件必须是布尔值。

For 循环

你可以对 iterate 化的变量进行循环遍历:

var message = StringBuffer('Dart is fun');
for (var i = 0; i < 5; i++) {
  message.write('!');
}

在 Dart 的 for 循环中,闭包体内会捕获索引的值,这样可以避免 JavaScript 中一个常见的隐患:

var callbacks = [];
for (var i = 0; i < 2; i++) {
  callbacks.add(() => print(i));
}
callbacks.forEach((c) => c());

像预期那样,先输出 0 然后是 1,但是在 JavaScript 中,会先输出 2,然后又输出 2

如果对象体是可以 Iterable 化的,可以使用 forEach() 去遍历。 如果你不需要知道当前迭代计数器,forEach() 是一个不错的选择:

candidates.forEach((candidate) => candidate.interview());

可 Iterable 化的类,比如 ListSet,同样支持 for-in

var collection = [0, 1, 2];
for (var x in collection) {
  print(x); // 0 1 2
}

while & do-while 循环

while 循环会在遍历之前判断条件,如果不满足,就不遍历:

while (!isDone()) {
  doSomething();
}

do-while 循环在遍历之后才判断条件,如果不满足,就不遍历

do {
  printLine();
} while (!atEndOfPage());

区别: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();
}

当使用 listset 这样可 Iterable 化的变量时,你可能会这样写代码:

candidates
    .where((c) => c.yearsExperience >= 5)
    .forEach((c) => c.interview());

分支(switch & case)

Dart 中的 switch 语句会用 == 去比较数字、字符串或编译常量。比较的对象必须是同一类型的对象实例(不能像 JavaScript 那样模糊比较,即使其中一个操作数属于另一个对象的子类的实例也不行),并且类也不能重写 == 运算符。

Note: 在 Dart 中,switch 语句会预先判断边界异常情况,比如在编译或代码扫描时。

按照规则,每一个非空的 case 分支要通过 break 语句进行结尾,使用 continuethrowreturn 语句进行结尾也是可以的。

如果都没有分支匹配上,使用 default 分支去处理:

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();
}

下面的例子忘记写 break 语句了,所以会报错:

var command = 'OPEN';
switch (command) {
  case 'OPEN':
    executeOpen();
    // ERROR: Missing break

  case 'CLOSED':
    executeClosed();
    break;
}

当然,Dart 支持空分支,允许下沉到下一个分支去统一处理:

var command = 'CLOSED';
switch (command) {
  case 'CLOSED': // Empty case falls through.
  case 'NOW_CLOSED':
    // Runs for both CLOSED and NOW_CLOSED.
    executeNowClosed();
    break;
}

如果你很希望分支下沉,使用 continue 语句并且指定 label,可以实现类似 goto 语句的功能:

var command = 'CLOSED';
switch (command) {
  case 'CLOSED':
    executeClosed();
    continue nowClosed;
  // Continues executing at the nowClosed label.

  nowClosed:
  case 'NOW_CLOSED':
    // Runs for both CLOSED and NOW_CLOSED.
    executeNowClosed();
    break;
}

case 分支可以拥有只有在自己作用域使用的本地变量;

Assert 断言

在开发过程中,可以使用 assert 语句 - assert(condition, optionalMessage) - 如果条件为假,则会中断正常的执行流程。

// 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 里当做第二参数传入一段字符串:

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

assert 的第一个参数是可以接受任何可以被转换为 Boolean 类型的对象(如果是函数,则判断函数返回值),如果参数为 true,断言就会成功,并且继续执行后面的代码。如果为 false , 断言就会终止程序并抛出一个 AssertionError 异常。

什么时候可以使用断言?,取决于你使用的库和框架:

  • Flutter 允许在调试模式(debug mode)中使用;
  • 只能在开发环境使用的库,比如dartdevc 默认支持断言;
  • 有些苦,比如 dartdart.dev/tools/dart2…,支持输入命令行:--enable-asserts 来开启断言

在生产环境中,断言会自动被忽略,传入断言的参数也不会被执行。

系列文章:

Dart 简明教程 - 01 - Concepts & Variables
Dart 简明教程 - 02 - Functions
Dart 简明教程 - 03 - Operators
Dart 简明教程 - 04 - Control flow statements
Dart 简明教程 - 05 - Exceptions
Dart 简明教程 - 06 - Classes
Dart 简明教程 - 07 - Generics
Dart 简明教程 - 08 - Libraries and visibility
Dart 简明教程 - 09 - Asynchrony support
Dart 简明教程 - 10 - Generators & Isolates & Typedefs & Metadata...