使用 Container 在 Dart 中类型安全
Type safety in Dart using Container
我在 dart 中发现了一些奇怪的东西。如果有一个包含基础 class 实例的列表(在本例中为 Super),则可以使用继承实例的列表来设置该列表。看来这会在运行时更改列表类型。
这是预期的行为还是 Dart 中的错误?
abstract class Super {}
class A extends Super {}
class B extends Super {}
class Container {
List<Super> mylist = [];
Container(this.mylist);
}
void main() {
// 1. dont't works
final container = Container(<A>[A(), A()]);
// 2. works
final container = Container([A(), A()]);
print(container.mylist.runtimeType);
container.mylist.add(B());
print(container.mylist);
}
如果在上面的代码中使用案例 1,我会得到以下错误:
JSArray<A>
Uncaught Error: TypeError: Instance of 'B': type 'B' is not a subtype of type 'A'
错误出现在我尝试添加 B 实例的行:
container.mylist.add(B());
Dart 有一个名为 type promotion, where it can promote the type of a variable, similar to type inference 的系统。
它作为 cast 工作。在第一个示例中,您已明确将列表类型提升为 A
类型,因此这没有什么奇怪的。
看看第一篇解释这个机制的文章。
当你这样做时:
final container = Container(<A>[A(), A()]);
您明确创建了一个 List<A>
对象。虽然 Container
的构造函数需要 List<Super>
,但它接受 List<A>
参数,因为 Dart 认为 Generic<Derived>
是 Generic<Base>
的子类型,如果 Derived
是 Base
的子类型。您稍后尝试执行 container.mylist.add(B());
将失败,因为 container.mylist
实际上是一个 List<A>
,因此不能合法地存储任何 B
元素。
当你改为:
final container = Container([A(), A()]);
然后,因为 List
字面量没有给出显式类型,所以根据 Container
的预期构造参数推断其类型为 List<Super>
。 container.mylist.add(B());
会成功,因为 container.mylist
实际上是一个 List<Super>
,因此可以合法地存储 B
个元素。
我在 dart 中发现了一些奇怪的东西。如果有一个包含基础 class 实例的列表(在本例中为 Super),则可以使用继承实例的列表来设置该列表。看来这会在运行时更改列表类型。
这是预期的行为还是 Dart 中的错误?
abstract class Super {}
class A extends Super {}
class B extends Super {}
class Container {
List<Super> mylist = [];
Container(this.mylist);
}
void main() {
// 1. dont't works
final container = Container(<A>[A(), A()]);
// 2. works
final container = Container([A(), A()]);
print(container.mylist.runtimeType);
container.mylist.add(B());
print(container.mylist);
}
如果在上面的代码中使用案例 1,我会得到以下错误:
JSArray<A>
Uncaught Error: TypeError: Instance of 'B': type 'B' is not a subtype of type 'A'
错误出现在我尝试添加 B 实例的行:
container.mylist.add(B());
Dart 有一个名为 type promotion, where it can promote the type of a variable, similar to type inference 的系统。
它作为 cast 工作。在第一个示例中,您已明确将列表类型提升为 A
类型,因此这没有什么奇怪的。
看看第一篇解释这个机制的文章。
当你这样做时:
final container = Container(<A>[A(), A()]);
您明确创建了一个 List<A>
对象。虽然 Container
的构造函数需要 List<Super>
,但它接受 List<A>
参数,因为 Dart 认为 Generic<Derived>
是 Generic<Base>
的子类型,如果 Derived
是 Base
的子类型。您稍后尝试执行 container.mylist.add(B());
将失败,因为 container.mylist
实际上是一个 List<A>
,因此不能合法地存储任何 B
元素。
当你改为:
final container = Container([A(), A()]);
然后,因为 List
字面量没有给出显式类型,所以根据 Container
的预期构造参数推断其类型为 List<Super>
。 container.mylist.add(B());
会成功,因为 container.mylist
实际上是一个 List<Super>
,因此可以合法地存储 B
个元素。