Dart泛型类类型异常:'(SpecificType)=>String'非'(dynamic)=>String'子类型
问题描述
编写Flutter模块化包的泛型Dart类时出现运行时类型异常,代码可正常编译,但执行时崩溃,错误信息为:
type '(Dog) => String' is not a subtype of type '(dynamic) => String'
复现代码如下:
void main() { var sc = Shelter<Cat>( name: 'test shelter', data: [Cat(id: 'cat-1', name: 'cat no.1')], extractParam: (data) => data.id, ); var sd = Shelter<Dog>( name: 'test shelter dog', data: [Dog(dogId: 'dog-1', name: 'dog no.1')], extractParam: (data) => data.dogId, ); print(sc.extractParam(Cat(id: 'cat-2', name: 'cat no.2'))); print(sd.extractParam(Dog(dogId: 'dog-2', name: 'dog no.2'))); var dog = Dog(dogId: 'dog-3', name: 'dog no.3'); var test = Test( data: dog, shelter: sd, ); test.printTest(); print("hello before testtest()"); for (var c in sc.data) { final d = sc.extractParam(c); print(d); } testtest(sd); } void testtest(Shelter shelter) { for (var a in shelter.data) { final b = shelter.extractParam(a); print(b); } } class Test<T> { final T data; final Shelter<T> shelter; const Test({ required this.data, required this.shelter, }); void printTest() => print('This is test: ${shelter.extractParam(data)}'); } class Dog { final String dogId; final String name; const Dog({ required this.dogId, required this.name, }); } class Cat { final String id; final String name; const Cat({ required this.id, required this.name, }); } class Shelter<T> { final String name; final List<T> data; final String Function(T data) extractParam; const Shelter({ required this.name, required this.data, required this.extractParam, }); }
运行日志:
➜ test_dart dart ./bin/test_generic_field_extract.dart cat-2 dog-2 This is test: dog-3 hello before testtest() cat-1 Unhandled exception: type '(Dog) => String' is not a subtype of type '(dynamic) => String' #0 testtest (file:///Users/tharineemunkwamdee/projects/test_dart/bin/test_generic_field_extract.dart:34:23) #1 main (file:///Users/tharineemunkwamdee/projects/test_dart/bin/test_generic_field_extract.dart:29:3) #2 _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:296:19) #3 _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:189:12) ➜ test_dart
错误原因
问题根源在testtest函数的参数定义:void testtest(Shelter shelter)省略了泛型参数,导致Dart将shelter推断为Shelter<dynamic>类型。
Shelter<T>中的extractParam是String Function(T)类型,当传入的是Shelter<Dog>时,extractParam实际是(Dog)=>String。但当shelter被当作Shelter<dynamic>处理时,Dart期望extractParam是(dynamic)=>String——由于(Dog)=>String只能接受Dog类型参数,无法兼容dynamic类型,因此触发类型不匹配的运行时异常。
解决方法
给testtest函数添加泛型参数,让它支持任意类型的Shelter<T>,确保类型一致:
- 修改函数定义为
void testtest<T>(Shelter<T> shelter) - 遍历
shelter.data时,每个元素类型为T,可直接被extractParam正确接收
修改后的完整代码
void main() { var sc = Shelter<Cat>( name: 'test shelter', data: [Cat(id: 'cat-1', name: 'cat no.1')], extractParam: (data) => data.id, ); var sd = Shelter<Dog>( name: 'test shelter dog', data: [Dog(dogId: 'dog-1', name: 'dog no.1')], extractParam: (data) => data.dogId, ); print(sc.extractParam(Cat(id: 'cat-2', name: 'cat no.2'))); print(sd.extractParam(Dog(dogId: 'dog-2', name: 'dog no.2'))); var dog = Dog(dogId: 'dog-3', name: 'dog no.3'); var test = Test( data: dog, shelter: sd, ); test.printTest(); print("hello before testtest()"); for (var c in sc.data) { final d = sc.extractParam(c); print(d); } testtest(sd); } // 添加泛型参数T,确保类型匹配 void testtest<T>(Shelter<T> shelter) { for (var a in shelter.data) { final b = shelter.extractParam(a); print(b); } } class Test<T> { final T data; final Shelter<T> shelter; const Test({ required this.data, required this.shelter, }); void printTest() => print('This is test: ${shelter.extractParam(data)}'); } class Dog { final String dogId; final String name; const Dog({ required this.dogId, required this.name, }); } class Cat { final String id; final String name; const Cat({ required this.id, required this.name, }); } class Shelter<T> { final String name; final List<T> data; final String Function(T data) extractParam; const Shelter({ required this.name, required this.data, required this.extractParam, }); }
运行结果
修改后执行代码,可正常输出所有结果,无异常:
cat-2 dog-2 This is test: dog-3 hello before testtest() cat-1 dog-1
内容的提问来源于stack exchange,提问作者fanggiz
相关产品推荐
相关产品推荐

