首页 > 解决方案 > Dart 给出未处理的异常:类型不是“值”类型的子类型

问题描述

我有一个抽象类ImageUpdate。两个类,NewImageExistingImage实现ImageUpdate.

我有一个imageUpdates类型的变量List<ImageUpdate>

当我尝试将类型变量添加NewImage到列表时,我收到此错误:

Unhandled Exception: type 'NewImage' is not a subtype of type 'ExistingImage' of 'value'

我很困惑,因为列表是 ofImageUpdate而不是ExistingImage,所以我不知道如何调试它,特别是因为 Dart 是类型安全的(我没有在任何地方使用dynamic)。

任何帮助将不胜感激,谢谢。

标签: darttypescasting

解决方案


我怀疑您的代码类似于:

class Base {}

class Derived1 extends Base {}

class Derived2 extends Base {}

List<Base> makeList() {
  var list = [Derived1()];
  return list;
}

void main() {
  var list = makeList();
  list.add(Derived2()); // TypeError
}

发生的情况是该List对象最初创建为List<Derived1>. (也就是说,list.runtimeType将类似于List<Derived1>,而不是它的静态(声明的)类型List<Base>。)然后,当您尝试将Derived2对象添加到list时,它将在运行时失败,因为list的实际运行时类型是List<Derived1>,它不允许Derived2元素。

这最终源于 Dart 允许隐式类型转换 from GenericClass<Derived>to GenericClass<Base>ifDerived派生自Base。这在许多情况下很有用,但它也可能导致像这样的情况在运行时失败。

您可以通过明确声明您想要一个List<Base>对象来解决此问题:

List<Base> makeList() {
  var list = <Base>[Derived1()]; // Note the explicit type.
  return list;
}

或者,如果这不可能,则通过创建一个新List<Base>对象:

  • var list = <Base>[...makeList()];
  • var list = List<Base>.from(makeList());

(在这种特殊情况下,List.of(makeList())也可以使用,因为它会创建一个List具有静态类型的新对象,但我不会使用它,因为明确类型转换会更具可读性。)


推荐阅读