flutter 访问列表中元素的泛型方法时出现运行时错误

ergxz8rk  于 2023-03-13  发布在  Flutter
关注(0)|答案(2)|浏览(251)
class A<T> {
  final T data;
  final T Function(T) convert;

  A(this.convert, this.data);

  Type get genericType => T;
}

void main(List<String> args) {
  final list = <A>[
    A<int>((i) => i + i, 0),
    A<String>((i) => i + i, '0'),
  ];

  print(list[0].data);    // ok
  print(list[0].convert); // runtime error: type '(int) => int' is not a subtype of type '(dynamic) => dynamic'
}

看起来dart认为函数类型不兼容。但是为什么这会发生在运行时,我应该如何解决它而不失去编译时类型检查的优势。

编辑:

我发现如果我在阅读这个函数之前向上转换元素,就可以了:

final first = list[0] as A<int>;
print(first.convert); // ok

所以我想找到一种在运行时动态上抛元素的方法,我添加了一个方法,根据其他stackoverflow的答案来获取类A的实际泛型类型。

Type get genericType => T;

如果我能做到这一点就太好了:

final t = list[0].genericType;
final first = list[0] as A<t>;
print(first.convert);

不幸的是我不能。作为一个肮脏的变通方案,如果我有一个有限的泛型数量,我可以这样做:

final t = list[0].genericType;
  if (t == int) {
    final first = list[0] as A<int>;
    print(first.convert);
  } else if (t == String) {
    final first = list[0] as A<String>;
    print(first.convert);
  }
wydwbb8l

wydwbb8l1#

发生这种情况是因为列表被声明为List<A>类型,它等价于List<A<dynamic>>,这导致编译器对dynamic进行类型检查。

print(list[0].data);    // compiler inferred: dynamic
print(list[0].convert); // compiler inferred: (dynamic) => dynamic

在运行时,第二个表达式成为了一个问题。对象实际上是(int) => int类型,强制int输入到函数中,而不是接受编译器所期望的dynamic的任何子类型。编译器的想法和运行时的说法之间的矛盾导致抛出异常。
不幸的是,除了重写整个构造之外,没有真实的的方法来解决这个问题。Dart是围绕着类型推理机制的,当你将列表转换为A<dynamic>时,编译器会丢失很多信息。

j0pj023g

j0pj023g2#

声明A<int>convert变为int Function (int);声明A<String>转换为String Function (String);由于jraufeisen Dart的答案中的原因,请将convert方法的T参数视为dynamic,并告知您参数类型不匹配(我个人同意您的编程方法,我希望在Dart未来版本的直接强制转换中可以解决此问题)。
不过,要解决您的问题,您只需执行以下操作:
将转换声明为:

final T Function(dynamic) convert;

或在A上不做任何更改,将参数类型转换为动态:

final List<A> list = <A>[
    A<int>((dynamic i) => i + i, 0),
    A<String>((dynamic i) => i + i, '0'),
  ];

相关问题