Dart 2.9中不再允许隐式下转换

309 阅读2分钟

随着完全类型安全的引入,Dart 2.9在默认情况下使编写更安全的代码变得更容易。

作为其中的一部分,隐式下转换不再被允许。

什么是隐式下转换?

考虑一下这段代码。

String s = 'hello world';
Object o = s; // upcast, allowed

你总是可以把一个String 的值赋给一个Object 的变量,因为Object 是Dart中所有类型的基类。

然而,到现在为止,你也可以这样做。

Object x = 42;
int i = x; // valid, x *holds* an int value
String s = x; // valid, but shouldn't be allowed

上面的赋值被称为隐式下转换,在Dart 2.8及以下版本中有效。

虽然你不会故意写这样的代码,但隐式下转换可以在你的代码中不被察觉。

考虑一下这个例子。

List<int> values = [1, 2, 3];
List<int> doubled = values.map((v) => v * 2);
print(doubled);
// TypeError: Instance of 'MappedListIterable<int, int>': type 'MappedListIterable<int, int>' is not a subtype of type 'List<int>'

看起来这段代码应该是有效的,但它却抛出了一个运行时异常。

这是因为mapIterable 类的一个方法,而 是List 的一个祖先类。

更确切地说,表达式values.map((v) => v * 2) 的类型是MappedListIterable<int, int> 。这可以被分配给一个类型为List<int> 的变量,因为隐式下转换是允许的。

但它不应该这样做!为了解决这个运行时异常,我们必须写。

List<int> doubled = values.map((v) => v * 2).toList();

很容易忘记.toList() - 我已经做了很多次了!

Dart 2.9中的隐式下划线

幸运的是,在Dart 2.9中不再允许隐式降调。

List<int> values = [1, 2, 3];
List<int> doubled = values.map((v) => v * 2);
// A value of type 'Iterable<int*>*' can't be assigned to a variable of type 'List<int>'

这段代码会产生一个编译错误。第一个例子也是不允许的。

Object x = 42; 
int i = x; // A value of type 'Object' can't be assigned to a variable of type 'int'
String s = x; // A value of type 'Object' can't be assigned to a variable of type 'String'

这样就好多了。

在analysis_options.yaml中禁用隐式下转换法

截止到2020年6月,Dart 2.9还没有进入稳定通道。

如果你是在Dart 2.8或以下版本,你可以在你的analysis_options.yaml 文件中禁用一些旧的 "动态 "规则。

analyzer:
  strong-mode:
    implicit-casts: false
    implicit-dynamic: false

这将迫使你使用显式下转换。

Object x = 42; 
int i = x as int; // compiles, legit
String s = x as String; // compiles, will throw runtime exception

有了明确的下转换,你就不太可能写出错误的代码。

同样地,前面的例子中的maptoList() 也会产生一个编译时错误。

List<int> values = [1, 2, 3];
List<int> doubled = values.map((v) => v * 2);
// A value of type 'Iterable<int>' can't be assigned to a variable of type 'List<int>'

结论

隐式下转换是Dart语言的一个不安全特性。你应该在analysis_options.yaml 中禁用它们。而在Dart 2.9中,它们将永远消失。😎

编码愉快!