A Tour of the Dart Language(译文):五控制流语句

原创
2018/10/16 10:55
阅读数 179

Dart代码可以使用下面的控制流语句:

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

Exceptions所描述的,可用trt-catchthrow来影响控制流语句。

if和else

Dart支持if语句与可选的else语句,如下面例子显示。还请查阅conditional expressions

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

与JavaScript不同,条件必须是布尔值。查阅更多Booleans信息。

For循环

遍历使用标准的for循环。例如:

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

Dart的闭包捕获for循环索引值。避免JavaScrip常见的陷阱。例如,考虑下:

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类如List和Set也支持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());

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如List或set,示例可以用不同的方式编写:

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

switch和case

Dart使用==比较switch语句中的整数、字符串或编译期常量。比较的对象必须是同一个类的实例 (不是它的任何子类型),且类不能覆盖==枚举类型switch语句中正常工作。

注意:在Dart中switch语句有限的情况下适用于,诸如interpreter和scanners。

规则,每个非空的case子句于break语句结尾。其他可行的方式是,非空case子句用continuethrowreturn语句结束。 当没匹配到case子句执行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();
}

下面的示例在case子句中省略break语句,导致错误:

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

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

但是, Dart允许下降(fall-through)的方式支持空case子句:

var command = 'CLOSED';
switch (command) {
  case 'CLOSED': // 空case下降.
  case 'NOW_CLOSED':
    //CLOSED和NOW_CLOSED都运行.
    executeNowClosed();
    break;
}

可以使用continue语句和标签在下降(fall-through)中:

var command = 'CLOSED';
switch (command) {
  case 'CLOSED':
    executeClosed();
    continue nowClosed;
  // 继续执行nowClosed标签.

  nowClosed:
  case 'NOW_CLOSED':
    //CLOSED和NOW_CLOSED都运行.
    executeNowClosed();
    break;
}

case子句里定义的变量,可见性仅在于子句作用域内。

断言

使用assert语句中断条件为false的正常执行。您可以在整个教程中找到断言语句的示例。这里有更多的:

// 确保变量为非空值
assert(text != null);

//确保值小于100
assert(number < 100);

// 确保是一个https链接
assert(urlString.startsWith('https'));

注意:assert语句在生产代码不起作用,它们只用于开发。Flutter在debug模式开启assert。开发工具如dartdevc一般默认支持断言。一些工具如dartdart2js通过命令行参数 --enable-asserts支持。

若要将消息附加到断言, 将字符串添加到第二个参数。

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

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

异常

Dart代码可以抛出和捕获异常。异常指示发生意外事件的错误。如果异常没有捕获,引发异常的isolate将被挂起,通常isolate和程序被终止。 对比Java,所有的dart异常都是未检异常。方法不用声明它要抛出的异常,且不强制捕获任何异常。 Dart提供ExceptionError类型,以及许多预定义的子类。当然您也可以定义自己的一场。但是, Dart 程序可以抛出任何非nul对象, 而不只是Exception和Error对象。

Throw

下面是抛出或引发异常的示例:

throw FormatException('Expected at least 1 section');

也可以抛出任意对象:

throw 'Out of llamas!';

注意:生成的代码抛出类型一般会实现ErrorException。 由于抛出异常是一个表达式,可以把抛出异常用在=>语句中,以及其他任何允许表达式的地方。

void distanceTo(Point other) => throw UnimplementedError();

Catch

捕捉或捕获,阻止异常传播 (除非rethrow 异常)。catch一个异常给你一个处理它的机会。

try {
  breedMoreLlamas();
} on OutOfLlamasException {
  buyMoreLlamas();
}

捕获代码可以处理不止一个异常类型,可指定多个catch子句。第一个匹配抛出类型对象catch子句处理异常。如果 catch 子句未指定类型, 则该子句可处理任何抛出对象类型(无catch子句匹配情况):

try {
  breedMoreLlamas();
} on OutOfLlamasException {
  //指定一个异常
  buyMoreLlamas();
} on Exception catch (e) {
  // 任何其他这是一个异常
  print('Unknown exception: $e');
} catch (e) {
  // 无指定类型,处理所有
  print('Something really unknown: $e');
}

on type catch(e)的语法实在别扭!

如果只要部分处理异常, 允许它继续传播, 请使用 rethrow 关键字。

void misbehave() {
  try {
    dynamic foo = true;
    print(foo++); // 运行时 error
  } catch (e) {
    print('misbehave() partially handled ${e.runtimeType}.');
    rethrow; // 运行调用者见到异常
  }
}

void main() {
  try {
    misbehave();
  } catch (e) {
    print('main() finished handling ${e.runtimeType}.');
  }
}

Finally

使用finally子句确保某些代码无论是否引发异常都执行。如果没有匹配catch子句异常, 则在最后一个子句运行后将传递异常:

try {
  breedMoreLlamas();
} finally {
  // 总是清理, 即使引发异常。
  cleanLlamaStalls();
}

finally子句在匹配任何catch子句后执行:

try {
  breedMoreLlamas();
} catch (e) {
  print('Error: $e'); // 首先处理异常
} finally {
  cleanLlamaStalls(); //然后清理.
}

阅读library速览的Exceptions部分了解更多内容。

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部