当list literal的元素与声明的泛型类型不匹配时,不会报告类型错误。为什么?

时间:2014-02-02 03:09:30

标签: generics dart typechecking

当我遇到以下代码时,我一直在Dart By Example通过Shailen Tuli的片段集合:

List<String> fruits = [
  {'name': 'apple', 'selected': true},
  {'name': 'banana', 'selected': true},
  {'name': 'kiwi', 'selected': false}
 ];

请注意,fruits被声明为List<String>,但列表元素实际上是地图。

问题:为什么没有报告类型错误?

1 个答案:

答案 0 :(得分:5)

如果代码示例是使用强静态类型语言编写的,则会报告错误。但 Dart 是:

  • 使用
  • 动态输入语言
  • 静态类型检查基于“乐观类型启发式系统 1

考虑这个声明:

List<num> lst = [4, "ty-two"];

重要的是要理解,给定的数组文字[4, "ty-two"]的类型为List<dynamic>,其中dynamic静态类型,归因于表达式,当静态类型系统不知道它是什么时(例如,用户没有声明静态类型),或者不想打扰进行更深入的分析以找出类型可能是什么 - 就像这样的情况对于列表lst的通用参数。

如果您声明文字列表元素的预期静态类型,静态类型系统只能指出存在类型错误:

List<num> lst = <num>[4, "tytoo"];
List<String> fruits = <Map>[{'name': 'apple', ...}, ...];

现在,在这两种情况下都会报告类型错误。在lst的情况下,乐观系统可以轻松地告诉String "ty-two"永远不会是num类型。类似的评论适用于fruits。另一方面,如果我们有

var a = "tytoo";
List<num> lst = <num>[4, a];

使用var声明变量有效地意味着(对于静态类型检查器)a类型为dynamic。因此,在lst的分配中没有报告错误。

详情见Language Specification和这两篇(恕我直言)优秀文章;他们解释了Dart的输入,同时也涵盖了与类型系统相关的语言设计决策背后的基本原理

-

1 https://www.dartlang.org/articles/why-dart-types/
2 https://www.dartlang.org/articles/optional-types/