什么是 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 -> int
var one = int.parse('1');
assert(one == 1);
// String -> double
var onePointOne = double.parse('1.1');
assert(onePointOne == 1.1);
// int -> String
String oneAsString = 1.toString();
assert(oneAsString == '1');
// double -> String
String 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 create
multi-line strings like this one.
''';
var s2 = """This is also a
multi-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 中文网