什么是 Dart

Dart 是一种易于学习、 易于扩展、并且可以部署到任何地方的应用编程语言。

logo-61576b6c2423c80422c986036ead4a7fc64c70edd7639c6171eba19e992c87d9.svg

它能开发以下应用:

  • Web:创建一个运行在浏览器中的应用
  • 移动:同一份代码编写运行在 iOS 和 Android 上的应用
  • 服务器:编写命令行脚本或者服务器应用

Frist Demo

  1. void main() { // 程序入口
  2. var number = 42; // 初始化变量
  3. printNumber(number); // 调用一个方法
  4. }
  5. void printNumber(num aNumber) { // 定义一个方法
  6. print('The number is $aNumber.');
  7. }

重要概念

  • 所有能够使用变量引用的都是对象, 每个对象都是一个的实例。在 Dart 中 甚至连 数字、方法和 null 都是对象。所有的对象都继承于 Object 类。
  • 使用静态类型(例如前面示例中的 num ) 可以更清晰的表明你的意图,并且可以让静态分析工具来分析你的代码, 但这并不是牵制性的。(在调试代码的时候你可能注意到 没有指定类型的变量的类型为 dynamic。)
  • Dart 在运行之前会先解析你的代码。你可以通过使用 类型或者编译时常量来帮助 Dart 去捕获异常以及 让代码运行的更高效。
  • Dart 支持顶级方法 (例如 main()),同时还支持在类中定义函数。 (静态函数和实例函数)。 你还可以在方法中定义方法 (嵌套方法或者局部方法)。
  • 同样,Dart 还支持顶级变量,以及 在类中定义变量(静态变量和实例变量)。 实例变量有时候被称之为域(Fields)或者属性(Properties)。
  • 和 Java 不同的是,Dart 没有 publicprotected、 和 private 关键字。如果一个标识符以 (_) 开头,则该标识符 在库内是私有的。
  • 标识符可以以字母或者 _ 下划线开头,后面可以是 其他字符和数字的组合。
  • 有时候 表达式 expression语句 statement 是有区别的,所以这种情况我们会分别指明每种情况。
  • Dart 工具可以指出两种问题:警告和错误。 警告只是说你的代码可能有问题, 但是并不会阻止你的代码执行。 错误可以是编译时错误也可以是运行时错误。遇到编译时错误时,代码将 无法执行;运行时错误将会在运行代码的时候导致一个异常。

默认值

没有初始化的变量自动获取一个默认值为 null。类型为数字的 变量如何没有初始化其值也是 null,不要忘记了 数字类型也是对象。

  1. int lineCount;
  2. assert(lineCount == null);

注意:在生产模式 assert() 语句被忽略了。在检查模式 assert(_condition_) 会执行,如果条件不为 true 则会抛出一个异常。详情请参考 Assert 部分。

可选的类型

在声明变量的时候,你可以选择加上具体 类型:

  1. String name = 'Bob';

添加类型可以更加清晰的表达你的意图。 IDE 编译器等工具有可以使用类型来更好的帮助你, 可以提供代码补全、提前发现 bug 等功能。

注意: 对于局部变量,这里准守代码风格推荐部分的建议,使用 var 而不是具体的类型来定义局部变量。

Final and const

如果你以后不打算修改一个变量,使用 final 或者 const。 一个 final 变量只能赋值一次;一个 const 变量是编译时常量。 顶级的 final 变量或者类中的 final 变量在第一次使用的时候初始化。

注意: 实例变量可以为 final 但是不能是 const

下面是 final 变量的示例:

  1. final name = 'Bob'; // Or: final String name = 'Bob';
  2. // name = 'Alice'; // Uncommenting this causes an error

const 变量为编译时常量。 如果 const 变量在类中,请定义为 static const。 可以直接定义 const 和其值,也 可以定义一个 const 变量使用其他 const 变量的值来初始化其值。

  1. const bar = 1000000; // Unit of pressure (dynes/cm2)
  2. const atm = 1.01325 * bar; // Standard atmosphere

const 关键字不仅仅只用来定义常量。 有可以用来创建不变的值, 还能定义构造函数为 const 类型的,这种类型 的构造函数创建的对象是不可改变的。任何变量都可以有一个不变的值。

  1. // Note: [] creates an empty list.
  2. // const [] creates an empty, immutable list (EIA).
  3. var foo = const []; // foo is currently an EIA.
  4. final bar = const []; // bar will always be an EIA.
  5. const baz = const []; // baz is a compile-time constant EIA.
  6. // You can change the value of a non-final, non-const variable,
  7. // even if it used to have a const value.
  8. foo = [];
  9. // You can't change the value of a final or const variable.
  10. // bar = []; // Unhandled exception.
  11. // baz = []; // Unhandled exception.

内置类型

Dart 内置支持下面这些类型:

  • numbers
  • strings
  • booleans
  • lists (也被称之为 arrays)
  • maps
  • runes (用于在字符串中表示 Unicode 字符)
  • symbols

你可以直接使用字母量来初始化上面的这些类型。 例如 'this is a string' 是一个字符串字面量, true 是一个布尔字面量。

由于 Dart 中每个变量引用的都是一个对象 – 一个类的实例, 你通常使用构造函数来初始化变量。 一些内置的类型具有自己的构造函数。例如, 可以使用 Map()构造函数来创建一个 map, 就像这样 new Map()

说明:Dart 1.x 是弱类型语言,2.x 后为强类型语言。

数值

intdouble 都是 num 的子类。 num 类型定义了基本的操作符,例如 +, -, /, 和 *, 还定了 abs()ceil()、和 floor() 等 函数。 (位操作符,例如 >> 定义在 int 类中。) 如果 num 或者其子类型不满足你的要求,请参考 dart:math 库。

下面是字符串和数字之间转换的方式:

  1. // String -> int
  2. var one = int.parse('1');
  3. assert(one == 1);
  4. // String -> double
  5. var onePointOne = double.parse('1.1');
  6. assert(onePointOne == 1.1);
  7. // int -> String
  8. String oneAsString = 1.toString();
  9. assert(oneAsString == '1');
  10. // double -> String
  11. String piAsString = 3.14159.toStringAsFixed(2);
  12. assert(piAsString == '3.14');

字符串

Dart 字符串是 UTF-16 编码的字符序列。 可以使用单引号或者双引号来创建字符串:

  1. var s1 = 'Single quotes work well for string literals.';
  2. var s2 = "Double quotes work just as well.";

可以在字符串中使用表达式,用法是这样的: ${expression}。如果表达式是一个基本类型,可以省略 {}。 如果表达式的结果为一个对象,则 Dart 会调用对象的 toString() 函数来获取一个字符串。

  1. var s = 'string interpolation';
  2. assert('Dart has $s, which is very handy.' ==
  3. 'Dart has string interpolation, ' +
  4. 'which is very handy.');
  5. assert('That deserves all caps. ' +
  6. '${s.toUpperCase()} is very handy!' ==
  7. 'That deserves all caps. ' +
  8. 'STRING INTERPOLATION is very handy!');

可以使用 + 操作符来把多个字符串链接为一个,也可以把多个 字符串放到一起来实现同样的功能:

  1. var s1 = 'String ' 'concatenation'
  2. " works even over line breaks.";
  3. assert(s1 == 'String concatenation works even over '
  4. 'line breaks.');
  5. var s2 = 'The + operator '
  6. + 'works, as well.';
  7. assert(s2 == 'The + operator works, as well.');

使用三个单引号或者双引号也可以 创建多行字符串对象:

  1. var s1 = '''
  2. You can create
  3. multi-line strings like this one.
  4. ''';
  5. var s2 = """This is also a
  6. multi-line string.""";

通过提供一个 r 前缀可以创建一个 “原始 raw” 字符串:

  1. var s = r"In a raw string, even \n isn't special.";

布尔值

为了代表布尔值,Dart 有一个名字为 bool 的类型。 只有两个对象是布尔类型的:truefalse 所创建的对象, 这两个对象也都是编译时常量。

当 Dart 需要一个布尔值的时候,只有 true 对象才被认为是 true。 所有其他的值都是 flase。这点和 JavaScript 不一样, 像 1"aString"、 以及 someObject 等值都被认为是 false。

Dart 这样设计布尔值,是为了避免奇怪的行为。很多 JavaScript 代码都遇到这种问题。 对于你来说,在写代码的时候你不用这些写代码: if (_nonbooleanValue_),你应该显式的判断变量是否为布尔值类型。例如:

  1. // Check for an empty string.
  2. var fullName = '';
  3. assert(fullName.isEmpty);
  4. // Check for zero.
  5. var hitPoints = 0;
  6. assert(hitPoints <= 0);
  7. // Check for null.
  8. var unicorn;
  9. assert(unicorn == null);
  10. // Check for NaN.
  11. var iMeantToDoThis = 0 / 0;
  12. assert(iMeantToDoThis.isNaN);

列表

也许 array (或者有序集合)是所有编程语言中最常见的集合类型。 在 Dart 中数组就是 List 对象。所以通常我们都称之为 lists

  1. var list = [1, 2, 3];

Lists 的下标索引从 0 开始,第一个元素的索引是 0. list.length - 1 是最后一个元素的索引。 访问 list 的长度和元素与 JavaScript 中的用法一样:

  1. var list = [1, 2, 3];
  2. assert(list.length == 3);
  3. assert(list[1] == 2);
  4. list[1] = 1;
  5. assert(list[1] == 1);

在 list 字面量之前添加 const 关键字,可以 定义一个不变的 list 对象(编译时常量):

  1. var constantList = const [1, 2, 3];
  2. // constantList[1] = 1; // Uncommenting this causes an error.

List 类型有很多函数可以操作 list。

Runes

在 Dart 中,runes 代表字符串的 UTF-32 code points。

Unicode 为每一个字符、标点符号、表情符号等都定义了 一个唯一的数值。 由于 Dart 字符串是 UTF-16 code units 字符序列, 所以在字符串中表达 32-bit Unicode 值就需要 新的语法了。

通常使用 \uXXXX 的方式来表示 Unicode code point, 这里的 XXXX 是4个 16 进制的数。 例如,心形符号 (♥) 是 \u2665。 对于非 4 个数值的情况, 把编码值放到大括号中即可。 例如,笑脸 emoji (😆) 是 \u{1f600}
String 类 有一些属性可以提取 rune 信息。 codeUnitAtcodeUnit 属性返回 16-bit code units。 使用 runes 属性来获取字符串的 runes 信息。

参考

【1】Dart 中文网