Dart泛型、库、异步和注释

1,938 阅读5分钟

欢迎点赞,转载请注明出处

泛型

  • < > 符号表示变量是一个泛型(或参数化类型),泛型可以更好地帮助代码生成,也可以减少代码重复。
  • List、Set 以及 Map 字面量也可以是参数化的。定义参数化的 List 只需在中括号前添加 <type>;定义参数化的 Map 只需要在大括号前添加 <keyType, valueType>。
  • 在调用构造方法时也可以使用泛型,只需在类名后用尖括号,如 Map<int,String>()。
  • 如果想限制泛型的类型范围,可以使用extends关键字,如class Study<T extends Human> 。
  • 泛型方法,如T first<T>(List ts) { }。

我们看一个简单的示例代码,结果输出Hello World和3.14:

class Test<T> {
  T obj;
  Test(T obj) {
    this.obj = obj;
  } 
  T getObject() {
    return this.obj;
  }
}
main() {
  Test<String> t1 = Test<String>("Hello World");
  print(t1.getObject());
  Test<double> t2 = Test<double>(3.14);
  print(t2.getObject());
}

  • import和library关键字可以创建一个模块化和可共享的代码库。每个Dart程序都是一个库,即便没有使用关键字 library 指定。
  • 代码库不仅只是提供 API 而且还起到了封装的作用:以下划线(_)开头的成员仅在代码库中可见。
  • 使用import来指定命名空间以便其它库可以访问。import的唯一参数是用于指定代码库的 URI,对于 Dart 内置的库,使用dart:xxxxxx的形式。而对于其它的库,可以使用一个文件系统路径或者以package:xxxxxx 的形式。后者通过包管理器(比如 pub 工具)来提供,如:import 'package:flutter/material.dart'

下图示例演示了import,library,export,part的基本用法,请留意这几个文件的位置组织结构。

Dart核心库

Dart提供了多种常见库, 便于开发者使用。

  • dart:async:支持通过使用 Future 和 Stream 这样的类实现异步编程。
  • dart:collection:提供 dart:core 库中不支持的额外的集合操作工具类。
  • dart:convert:用于提供转换不同数据的编码器和解码器,包括 JSON 和 UTF-8。
  • dart:core:每一个 Dart 程序都可能会使用到的内置类型、集合以及其它的一些核心功能。
  • dart:math:包含算术相关函数和常量,还有随机数生成器。
  • dart:io:用于支持非 Web 应用的文件、Socket、HTTP 和其它 I/O 操作。
  • dart:isolate:使用 Isolate 实现并发编程:类似于线程的独立的 Worker。

如下例代码,输出一个大于等于0,小于100的随机整数。

import 'dart:math';

void main(){
  Random r=Random();
  print(("random number is ${r.nextInt(100)}"));
}

异步支持

  • Dart代码运行在单个执行“线程”中。Dart代码库中有大量返回Future或Stream对象的函数,这些函数都是异步的,它们会在耗时操作(比如I/O,网络请求)执行完毕前直接返回而不会等待耗时操作执行完毕。
  • Future对象被用于表示将来某个时刻一个潜在的值或错误,Future的接收器能够注册一个回调函数用于当这个值或错误可用时处理这个值或错误。 Stream对象提供了一种接收事件序列的方法,每个事件可以是一个数据事件(stream的元素),或是一个错误事件。当一个stream发送完它的所有时间,一个独立的"done"事件将会通知监听器事件的结束。
  • async和await关键字用于实现异步编程,它们跟Javascript ES6中的async和await作用是一样的。await 表达式的返回值通常是一个Future对象,await 表达式会阻塞直到需要的对象返回。await 需要在一个异步函数中使用,定义异步函数只需在普通方法上加上async关键字即可。

我们将在Widget状态和应用数据管理一章给出async和await的使用实例,你可以运行下面的代码看下打印语句的输出顺序。

Future main() async {
  var value = 100000;
  print("call await _waitForValue(value) begin");
  await _waitForValue(value);
  print("call await _waitForValue(value) end");

  print("call _waitForValue(value) begin");
  _waitForValue(value);
  print("call _waitForValue(value) end");
}

Future _waitForValue(int n) => Future(() {
      // Do some long process
      for (var i = 1; i <= n; i++) {
        // Print out progress:
        if ([n / 2, n / 10].contains(i)) {
          print("Not done yet...");
        }
        // Return value when done.
        if (i == n) {
          print("Done.");
          return ;
        }
      }
      return ;
    });

文档注释

  • 文档注释可以是多行注释,也可以是单行注释,文档注释以 /// 或者 /** 开始。在连续行上使用 /// 与多行文档注释具有相同的效果。
  • 在 /// 或者 /** 注释中,使用中括号[ ]引用类、方法、字段、顶级变量、函数和参数会被解析,MarkDown语法解析同样也被支持。
  • 我们可以解析Dart代码并生成HTML文档,使用Dart SDK命令dartdoc

如果出现以下错误:
Unhandled exception: Unable to generate documentation: no package found
则需要在项目根目录上建立一个pubspec.yaml构建文件,只需定义name属性即可。
如果出现以下错误:
dartdoc failed: dartdoc could not find any libraries to document.
则需要在项目根目录下建立 lib\main.dart文件。
命令运行成功后,会在项目的doc\api目录下自动生成各种文档文件。包括自动生成的文档文件,整个项目结构如下图效果:

在浏览器里打开doc\api\index.html文件
点击各个链接可以看到///注释里对应的描述内容。代码注释不只是提供自己使用,更多地也是提供给他人使用的。良好的代码注释是非常重要的编程规范。

实验五

为之前的实验四的类和方法增加注释,并生成HTML文档。

  • 挑战:定义一个泛型方法,实现统计Words和CodeLine个数的通用方法。

至此,Dart编程的主要知识点已经介绍完毕,与Dart相关的教程部分示例点击这里DartExamples下载。

上一篇 Dart函数、运算符、异常和类 下一篇 Widget概览