Dart 语言是动态类型的。你可以编写、运行没有类型标注的任何程序,就像你使用Javascript的方式。

推荐专题:Google Dart新结构化编程语言
你可以在程序中添加类型标注:
◆ 添加类型不会阻止你程序的编译和运行——即使标注不完整或错误。
◆ 不论你添加了什么类型标注,你的程序都具有完全相同的语义。
然而,添加类型标注可以使你获益。类型提供了下面这些好处:
◆ 给人看的文档。明智地放置类型标注可以使别人更容易地阅读你的代码。
◆ 给机器看的文档。工具可以有多种方式利用类型标注。特别是,它们可以在 IDE 中帮助提供很好的特性,如名称补全和增强的导航。
◆ 早期的错误检测。Dart 提供了静态检查器,它可以警告你潜在的问题,而不用你自己查。另外,在开发模式中,Dart 自动把类型标注转换为运行时断言检查来辅助调试。
◆ 有时,在编译到 Javascript 时,类型可以帮助改进性能。
静态检查器
静态检查器(static checker)行为很像C中的链接。它在编译时警告你潜在的问题。这些警告中的很多是和类型相关的。静态检查器不会产生错误——不论检查器说什么你总是可以编译和运行你的代码。
检查器不会对每个可能的类型违反都敏感。它不是类型检查器(typechecker),因为Dart并不是按照典型的类型系统那样使用类型。检查器会抱怨那些非常可能是真实问题的地方,而不会强迫你去满足心胸狭隘的类型系统。
例如,考虑这个:
- String s1 = '9';
- String s2 = '1';
- ...
- int n = s1 + s2;
- print(n);
这里明显是个问题。这种情况下静态检查器会产生一个警告。注意代码依然可以运行,n 被置为字符串'91'并打印出来。
然而,不像典型的强类型系统,这样的代码:
- Object lookup(String key) {...} // a lookup method in a heterogenous table
- String s = lookup('Frankenstein');
检查器不会抱怨。因为这种情况下代码很有可能是对的,虽然缺少类型信息。你作为程序员通常知道程序的语义,而类型检查器(typechecker)不知道。你知道'Frankenstein'这个key在表中存储的是字符串,即使 lookup 方法声明返回的是Object。
Dynamic类型
没有提供类型的时候,Dart如何避免抱怨呢?这其中的关键就是 Dynamic 类型,这是程序员没有明确给出类型时候的默认类型。使用 Dynamic 类型让检查器闭嘴。
偶尔,你可能想要明确地使用 Dynamic 。
- Map m = {
- 'one': new Partridge(),
- 'two': new TurtleDove(),
- ...,
- 'twelve': new Drummer()};
我们本来也可以给m使用 Map ,但是那样的话,当我们获取内容的时候,它们将是Object的静态类型,而它只有很少的信息。因为map的内容除了Object外没有公共的super接口,我们可能更愿意使用 Dynamic 。如果我们像这样调用map 的值的方法:
- pearTree = m['one'].container();
如果内容是Object类型,我们会得到警告,因为Object不支持container方法。如果我们使用Dynamic类型,就不会产生警告。
范型
Dart 支持具体化范型(reified generics)。就是说,范型类型的对象在运行时携带它们的类型参数。传递类型参数给范型类型的构造函数是运行时操作。这如何与可选类型的要求相一致呢?
好吧,如果你不想总是考虑类型,范型并不强迫你。你可以创建范型类的实例,而不需要提供类型参数。例如,这样写没问题:
- new List();
当然,如果你想要,也可以这样写:
- new List();
- new List();
是下面这样的快捷方式:
- new List();
在构造函数中,类型参数起到运行时角色。实际上,它们在运行时被传递,所以你可以做动态类型测试的时候使用它们。
- new List() is List