什么是 Dart
Dart 是一种易于学习、 易于扩展、并且可以部署到任何地方的应用编程语言。
它能开发以下应用:
- Web:创建一个运行在浏览器中的应用
- 移动:同一份代码编写运行在 iOS 和 Android 上的应用
- 服务器:编写命令行脚本或者服务器应用
Frist Demo
void main() { // 程序入口var number = 42; // 初始化变量printNumber(number); // 调用一个方法}void printNumber(num aNumber) { // 定义一个方法print('The number is $aNumber.');}
重要概念
- 所有能够使用变量引用的都是对象, 每个对象都是一个类的实例。在 Dart 中 甚至连 数字、方法和
null都是对象。所有的对象都继承于 Object 类。 - 使用静态类型(例如前面示例中的
num) 可以更清晰的表明你的意图,并且可以让静态分析工具来分析你的代码, 但这并不是牵制性的。(在调试代码的时候你可能注意到 没有指定类型的变量的类型为dynamic。) - Dart 在运行之前会先解析你的代码。你可以通过使用 类型或者编译时常量来帮助 Dart 去捕获异常以及 让代码运行的更高效。
- Dart 支持顶级方法 (例如
main()),同时还支持在类中定义函数。 (静态函数和实例函数)。 你还可以在方法中定义方法 (嵌套方法或者局部方法)。 - 同样,Dart 还支持顶级变量,以及 在类中定义变量(静态变量和实例变量)。 实例变量有时候被称之为域(Fields)或者属性(Properties)。
- 和 Java 不同的是,Dart 没有
public、protected、 和private关键字。如果一个标识符以 (_) 开头,则该标识符 在库内是私有的。 - 标识符可以以字母或者 _ 下划线开头,后面可以是 其他字符和数字的组合。
- 有时候 表达式 expression 和 语句 statement 是有区别的,所以这种情况我们会分别指明每种情况。
- Dart 工具可以指出两种问题:警告和错误。 警告只是说你的代码可能有问题, 但是并不会阻止你的代码执行。 错误可以是编译时错误也可以是运行时错误。遇到编译时错误时,代码将 无法执行;运行时错误将会在运行代码的时候导致一个异常。
默认值
没有初始化的变量自动获取一个默认值为 null。类型为数字的 变量如何没有初始化其值也是 null,不要忘记了 数字类型也是对象。
int lineCount;assert(lineCount == null);
注意:在生产模式 assert() 语句被忽略了。在检查模式 assert(_condition_) 会执行,如果条件不为 true 则会抛出一个异常。详情请参考 Assert 部分。
可选的类型
在声明变量的时候,你可以选择加上具体 类型:
String name = 'Bob';
添加类型可以更加清晰的表达你的意图。 IDE 编译器等工具有可以使用类型来更好的帮助你, 可以提供代码补全、提前发现 bug 等功能。
注意: 对于局部变量,这里准守代码风格推荐部分的建议,使用 var 而不是具体的类型来定义局部变量。
Final and const
如果你以后不打算修改一个变量,使用 final 或者 const。 一个 final 变量只能赋值一次;一个 const 变量是编译时常量。 顶级的 final 变量或者类中的 final 变量在第一次使用的时候初始化。
注意: 实例变量可以为 final 但是不能是 const 。
下面是 final 变量的示例:
final name = 'Bob'; // Or: final String name = 'Bob';// name = 'Alice'; // Uncommenting this causes an error
const 变量为编译时常量。 如果 const 变量在类中,请定义为 static const。 可以直接定义 const 和其值,也 可以定义一个 const 变量使用其他 const 变量的值来初始化其值。
const bar = 1000000; // Unit of pressure (dynes/cm2)const atm = 1.01325 * bar; // Standard atmosphere
const 关键字不仅仅只用来定义常量。 有可以用来创建不变的值, 还能定义构造函数为 const 类型的,这种类型 的构造函数创建的对象是不可改变的。任何变量都可以有一个不变的值。
// Note: [] creates an empty list.// const [] creates an empty, immutable list (EIA).var foo = const []; // foo is currently an EIA.final bar = const []; // bar will always be an EIA.const baz = const []; // baz is a compile-time constant EIA.// You can change the value of a non-final, non-const variable,// even if it used to have a const value.foo = [];// You can't change the value of a final or const variable.// bar = []; // Unhandled exception.// 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 后为强类型语言。
数值
int 和 double 都是 num 的子类。 num 类型定义了基本的操作符,例如 +, -, /, 和 *, 还定了 abs()、ceil()、和 floor() 等 函数。 (位操作符,例如 >> 定义在 int 类中。) 如果 num 或者其子类型不满足你的要求,请参考 dart:math 库。
下面是字符串和数字之间转换的方式:
// String -> intvar one = int.parse('1');assert(one == 1);// String -> doublevar onePointOne = double.parse('1.1');assert(onePointOne == 1.1);// int -> StringString oneAsString = 1.toString();assert(oneAsString == '1');// double -> StringString piAsString = 3.14159.toStringAsFixed(2);assert(piAsString == '3.14');
字符串
Dart 字符串是 UTF-16 编码的字符序列。 可以使用单引号或者双引号来创建字符串:
var s1 = 'Single quotes work well for string literals.';var s2 = "Double quotes work just as well.";
可以在字符串中使用表达式,用法是这样的: ${expression}。如果表达式是一个基本类型,可以省略 {}。 如果表达式的结果为一个对象,则 Dart 会调用对象的 toString() 函数来获取一个字符串。
var s = 'string interpolation';assert('Dart has $s, which is very handy.' =='Dart has string interpolation, ' +'which is very handy.');assert('That deserves all caps. ' +'${s.toUpperCase()} is very handy!' =='That deserves all caps. ' +'STRING INTERPOLATION is very handy!');
可以使用 + 操作符来把多个字符串链接为一个,也可以把多个 字符串放到一起来实现同样的功能:
var s1 = 'String ' 'concatenation'" works even over line breaks.";assert(s1 == 'String concatenation works even over ''line breaks.');var s2 = 'The + operator '+ 'works, as well.';assert(s2 == 'The + operator works, as well.');
使用三个单引号或者双引号也可以 创建多行字符串对象:
var s1 = '''You can createmulti-line strings like this one.''';var s2 = """This is also amulti-line string.""";
通过提供一个 r 前缀可以创建一个 “原始 raw” 字符串:
var s = r"In a raw string, even \n isn't special.";
布尔值
为了代表布尔值,Dart 有一个名字为 bool 的类型。 只有两个对象是布尔类型的:true 和 false 所创建的对象, 这两个对象也都是编译时常量。
当 Dart 需要一个布尔值的时候,只有 true 对象才被认为是 true。 所有其他的值都是 flase。这点和 JavaScript 不一样, 像 1、 "aString"、 以及 someObject 等值都被认为是 false。
Dart 这样设计布尔值,是为了避免奇怪的行为。很多 JavaScript 代码都遇到这种问题。 对于你来说,在写代码的时候你不用这些写代码: if (_nonbooleanValue_),你应该显式的判断变量是否为布尔值类型。例如:
// Check for an empty string.var fullName = '';assert(fullName.isEmpty);// Check for zero.var hitPoints = 0;assert(hitPoints <= 0);// Check for null.var unicorn;assert(unicorn == null);// Check for NaN.var iMeantToDoThis = 0 / 0;assert(iMeantToDoThis.isNaN);
列表
也许 array (或者有序集合)是所有编程语言中最常见的集合类型。 在 Dart 中数组就是 List 对象。所以通常我们都称之为 lists。
var list = [1, 2, 3];
Lists 的下标索引从 0 开始,第一个元素的索引是 0. list.length - 1 是最后一个元素的索引。 访问 list 的长度和元素与 JavaScript 中的用法一样:
var list = [1, 2, 3];assert(list.length == 3);assert(list[1] == 2);list[1] = 1;assert(list[1] == 1);
在 list 字面量之前添加 const 关键字,可以 定义一个不变的 list 对象(编译时常量):
var constantList = const [1, 2, 3];// 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 信息。 codeUnitAt 和 codeUnit 属性返回 16-bit code units。 使用 runes 属性来获取字符串的 runes 信息。
参考
【1】Dart 中文网
