A Tour of the Dart Language
一个基础的Dart程序
以下的代码使用了许多Dart最基础的特性:
// Define a function.
printInteger(int aNumber) {
print('The number is $aNumber.'); // Print to console.
}
// This is where the app starts executing.
main() {
var number = 42; // Declare and initialize a variable.
printInteger(number); // Call a function.
}
以下是针对所有(或几乎所有)Dart apps都会使用到的东西:
// This is a comment.
一个单行注释。Dart也支持多行注释和文档注释。
int
表示类型。还有一些其他的内置类型,如String、List以及bool。
42
数字文字。数字文字是一种编译时常数。
print()
一个展示输出内容的便捷的方式。
$variableName (or ${expression})
字符串插值:在字符串文本中包含变量或表达式的字符串等效项。
main()
启动应用程序执行的特殊、必需的顶级函数。
var
一种定义不指定类型的变量的方法。
重要的概念
在学习DART语言时,请记住以下事实和概念:
- 可以放在变量中的所有东西都是对象,每个对象都是类的实例。偶数、函数和NULL都是对象。所有对象都继承自Object类。
- 虽然Dart是强类型的,但类型注释是可选的,因为Dart可以推断类型。在上面的代码中,数字被推断为int类型。如果要显式声明不需要任何类型,请使用特殊类型Dynamic。
- Dart支持泛型类型,如List
(整数列表)或List (任何类型的对象列表)。 - Dart支持顶级函数(如main())以及绑定到类或对象的函数(分别为静态方法和实例方法)。您还可以在函数中创建函数(嵌套或本地函数)。
- 类似地,Dart支持顶级变量,以及绑定到类或对象(静态和实例变量)的变量。实例变量有时称为字段或属性。
- 与Java不同,Dart没有public、protected和private关键字。如果标识符以下划线(_)开头,则该标识符对其库是私有的。
- 标识符可以字母或下划线(_)开头,后跟这些字符加数字的任何组合。
- 需要清楚的界定好某条语句是一个表达式还是陈述式。
- Dart工具可以报告两种类型的问题:警告和错误。警告只是表明您的代码可能无法工作,但它们并不妨碍程序的执行。错误可以是编译时错误,也可以是运行时错误。编译时错误根本阻止代码执行;运行时错误会导致在代码执行时引发异常。
关键字
下表列出了DART语言专门处理的单词。
上标1的单词是内置标识符。避免使用内置标识符作为标识符。如果您试图为类名或类型名使用内置标识符,则会发生编译时错误。
带有上标2的两个字是较新的、有限的保留字,它们与在DART 1.0版本之后添加的异步支持有关。您不能在任何用异步、异步或同步标记的函数体中使用async, await或 yield作为标识符。有关更多信息,请参见异步支持。
关键字表中的所有其他字都是保留字。不能使用保留字作为标识符。
变量
下面是创建变量并对其进行初始化的示例:
var name = 'Bob';
变量存储引用。名为name的变量包含一个带有“Bob”值的字符串对象的引用。
name变量的类型推断为String,但您可以通过指定它来更改该类型。如果对象不限于单个类型,请按照设计准则指定对象或动态类型。
dynamic name = 'Bob';
另一种选择是显式声明可能推断的类型:
String name = 'Bob';
Note:本页遵循《编码风格指南》,对局部变量使用var而不是类型注释。
默认值
未初始化变量的初始值为null。即使是数值类型的变量,初始值也是null,因为数字就像Dart中的其他东西一样,也是对象。
int lineCount;
assert(lineCount == null);
在生产代码中 assert()
的调用会被忽略。在开发过程中,除非条件为真,否则 assert(condition)
。有关详细信息,请参见断言。
Final and const
如果您不希望更改变量,请使用Final或const来取代var,或者除此之外额外再加上一个类型声明。一个final变量只能被赋值一次。常量变量是编译时常数.(常量变量是隐式的final变量。)一个final的顶级变量或类变量在第一次使用时被初始化。
Note:实例变量可以是final,但不能是const。
下面是创建和设置一个final变量的示例:
final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
你无法更改一个final变量的值:
name = 'Alice'; // Error: a final variable can only be set once.
对希望成为编译时常量的变量使用const。如果const变量是class级别,则将其标记为static const。在声明变量时,将值设置为编译时常量,如数字或字符串文字、常量变量或常量算术运算的结果:
const bar = 1000000; // Unit of pressure (dynes/cm2)
const double atm = 1.01325 * bar; // Standard atmosphere
const关键字不仅仅用于声明常量变量。您还可以使用它来创建常量值,以及声明创建常量值的构造函数。任何变量都可以有一个常量值。
var foo = const [];
final bar = const [];
const baz = []; // Equivalent to `const []`
您可以在const声明的初始化表达式中省略const,就像上面的Baz一样。有关详细信息,请参见不要重复使用const。您可以更改不是final、不是const的值,即使它之前有一个常量值:
foo = [1, 2, 3]; // Was const []
无法更改常量变量的值:
baz = [42]; // Error: Constant variables can't be assigned a value.
有关使用const创建常量值的详细信息,请参阅 Lists, Maps, 和 Classes。
内置类型
DART语言特别支持以下类型:
- numbers
- strings
- booleans
- lists (also known as arrays)
- maps
- runes (for expressing Unicode characters in a string)
- symbols
可以使用文本初始化这些特殊类型的任何对象。例如, 'this is a string'
是一个字符串文本,而 true
是一个布尔文本。
因为Dart中的每个变量都指向一个对象—— 一个类的实例 —— 您通常可以使用构造函数来初始化变量。有些内置类型有自己的构造函数。例如,您可以使用 Map()
构造函数来创建映射。
数字
Dart Numbers 有两种:int
整数值不大于64位,具体取决于平台。在Dart虚拟机上, 取值范围为 -263~263-1。使用JavaScript Numbers编译为JavaScript的DART,允许值为-253~253-1。
double
64位(双精度)浮点数,符合IEEE 754标准。
int
和double
都是num
的子类型。num类型包括基本运算符,例如+、-、/和,您还可以在其中找到abs()
、cill()
和log()
等方法。(像 >> 这样的位运算符是在int类中定义的。)如果num及其子类型没有您要寻找的内容,则dart:math库可能会包含。
Integers是没有小数点的数字。下面是一些定义整数文本的示例:
Dart
int x = 1;
int hex = 0xDEADBEEF;
如果一个数字包含小数点,那么它就是double。下面是一些定义double文本的示例:
Dart
double y = 1.1;
double exponents = 1.42e5;
下面是如何将字符串转换为数字的方法,反之亦然:
Dart
// 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');
int类型支持传统的位移(<<,>>),与(&)和或(|)运算符。例如:
Dart
assert((3 << 1) == 6); // 0011 << 1 == 0110
assert((3 >> 1) == 1); // 0011 >> 1 == 0001
assert((3 | 4) == 7); // 0011 | 0100 == 0111
数字是编译时的常量。许多算术表达式也是编译时的常量。它们的运算结果也是可以计算到数字的编译时常量。
``` Dart
const msPerSecond = 1000;
const secondsUntilRetry = 5;
const msUntilRetry = secondsUntilRetry msPerSecond;
```
字符串
DART字符串是UTF-16编码的单元序列。可以使用单引号或双引号创建字符串:
var s1 = 'Single quotes work well for string literals.';
var s2 = "Double quotes work just as well.";
var s3 = 'It\'s easy to escape the string delimiter.';
var s4 = "It's even easier to use the other delimiter.";
你可以通过使用${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!');
Note:==操作符可以测试两个对象是否相等。如果两个字符串包含相同的代码单元序列,则它们是相等的。
你可以让字符串保持相邻或者使用+运算符来连接字符串:
ar 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创建一个”原始”的字符串:
var s = r'In a raw string, not even \n gets special treatment.'
如何在字符串中表示Unicode字符,请参考Runes获取详情。
字符串文本是编译时常量,只要任何插值表达式的值是null或数字、字符串或布尔值,它都是一个编译时常量。
// These work in a const string.
const aConstNum = 0;
const aConstBool = true;
const aConstString = 'a constant string';
// These do NOT work in a const string.
var aNum = 0;
var aBool = true;
var aString = 'a string';
const aConstList = [1, 2, 3];
const validConstString = '$aConstNum $aConstBool $aConstString';
// const invalidConstString = '$aNum $aBool $aString $aConstList';
有关使用字符串的详细信息,请参阅字符串和正则表达式。
布尔
为了表示布尔值,DART有一个命名为bool的类型。只有两个对象具有bool类型:布尔文本true和false,它们都是编译时常量。
DART的类型安全性意味着您不能使用以下代码if(nonbooleanValue)
或assert (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);
列表
在几乎所有编程语言中,可能最常见的集合就是数组了,或者说是有序的对象组。在Dart中,数组是List对象,所以大多数人都叫它们列表。
Dart list文本与JavaScript数组文本。下面是一个简单的Dart list:
var list = [1, 2, 3];
Note:分析器推断list具有类型List
。如果尝试向此列表添加非整数对象,分析器分析或程序运行时将引发错误。有关更多信息,请阅读类型推断。
list使用零基索引,其中0是第一个元素的索引,list.length - 1是最后一个元素的索引。你可以得到一个列表的长度,并像在JavaScript中一样引用列表元素:
var list = [1, 2, 3];
assert(list.length == 3);
assert(list[1] == 2);
list[1] = 1;
assert(list[1] == 1);
要创建一个编译时常量的列表,请在list之前添加const:
var constantList = const [1, 2, 3];
// constantList[1] = 1; // Uncommenting this causes an error.
list类型有许多方便的操作列表的方法。有关list的更多信息,请参阅Generics 和 Collections.。
映射
一般来说,映射是关联键和值的对象。键和值都可以是任何类型的对象。每个键只出现一次,但是您可以多次使用相同的值。Dart通过map文本和map类型提供对map的支持。一下有一些简单的Dart map示例,通过map文本创建:
var gifts = {
// Key: Value
'first': 'partridge',
'second': 'turtledoves',
'fifth': 'golden rings'
};
var nobleGases = {
2: 'helium',
10: 'neon',
18: 'argon',
};
Note:分析器推断,
gifts
拥有类型Map<String, String>
,noblegase
拥有类型Map。如果您试图将错误类型的值添加到map中,那么解析或运行时就会出现错误。要了解更多信息,请阅读有关类型推断的内容。
您可以使用Map构造器创建相同的对象:
var gifts = Map();
gifts['first'] = 'partridge';
gifts['second'] = 'turtledoves';
gifts['fifth'] = 'golden rings';
var nobleGases = Map();
nobleGases[2] = 'helium';
nobleGases[10] = 'neon';
nobleGases[18] = 'argon';
注意:您可能期望看到new Map()
而不是Map()
。在Dart 2中,new
关键字是可选的。有关详细信息,请参阅使用构造函数。
在现有的Map中添加一个新的键-值对,就像在JavaScript中一样:
var gifts = {'first': 'partridge'};
gifts['fourth'] = 'calling birds'; // Add a key-value pair
如果你查找一个不在map上的键,你会得到一个空值:
var gifts = {'first': 'partridge'};
assert(gifts['fifth'] == null);
使用.length
来获得map中键-值对的数量:
var gifts = {'first': 'partridge'};
gifts['fourth'] = 'calling birds';
assert(gifts.length == 2);
要创建一个编译时常量的map,在map文本之前添加const:
final constantMap = const {
2: 'helium',
10: 'neon',
18: 'argon',
};
// constantMap[2] = 'Helium'; // Uncommenting this causes an error.
有关map的更多信息,请参阅 Generics 和 Maps。
Runes
在Dart中,runes是UTF-32码点(Code Point)的字符串。Unicode为世界上所有书写系统中使用的每个字母、数字和符号定义了唯一的数字值。由于Dart字符串是UTF-16代码单元的序列,所以在字符串中表示32位Unicode值需要特殊的语法。
通常表示Unicode编码点的方法是\uXXXX,其中XXXX是4位十六进制值。例如,字符(♥)的表示方式为\u2665
。若要指定多于或少于4个十六进制数字,请将值置于花括号内。例如,笑的emoji字符(😆)是\u{1f600}
。
String类有几个属性可用于获取rune信息。codeUnitAt
和codeUnit
属性返回16位代码单元。使用runes属性获得runes的字符串。
下面的示例说明了runes、16位代码单元和32位码点之间的关系。
Note:使用list操作runes时要小心。根据特定的语言、字符集和操作,这种方法很容易崩溃。有关更多信息,请参见Stack Overflow上的如何在Dart中反转字符串。