Flutter泛型Builder函数类型不匹配问题求助
泛型Builder函数类型不匹配问题解决
问题描述
遇到类型转换错误:
type '(BuildContext, AppResources?, Widget?) => Widget' is not a subtype of type '((BuildContext, Object?, Widget?) => Widget)?'
明明AppResources?是Object?的子类型,为什么整个方法签名无法兼容?使用非泛型的SimpleBuilder时可以正常运行,请问如何正确使用泛型的GenericsBuilder<GEN>?
相关代码定义
typedef SimpleBuilder = Widget Function(BuildContext context, Object? object, Widget? child); typedef GenericsBuilder<GEN extends Object> = Widget Function(BuildContext context, GEN? object, Widget? child); class AppLocalization<RES extends Object> extends StatefulWidget { final Widget? child; final SimpleBuilder? builder; //final GenericsBuilder<RES>? builder; final Locale? defaultLocale; const AppLocalization({this.child, this.builder, this.defaultLocale, super.key}) : assert(builder != null || child != null); @override AppLocalizationState createState() => AppLocalizationState<RES>(); } class AppLocalizationState<RES extends Object> extends State<AppLocalization> { RES? _resources; @override void initState() { super.initState(); _resources = AppResources(); // 实际项目中初始化逻辑不同 } @override Widget build(BuildContext context) { return widget.builder?.call(context, _resources, widget.child) ?? widget.child!; } }
使用代码
@override Widget build(BuildContext context) { return AppLocalization<AppResources>( builder: (context, res, child) => res == null ? const SizedBox.shrink() : const Text('hurray') ); }
原因分析
Dart的函数参数类型遵循逆变规则:当需要一个接收Object?参数的函数时,传入的函数必须能接收Object?的超类型,而不是子类型。你传入的函数只接受AppResources?(Object?的子类型),无法处理任意Object?类型的参数,因此类型不兼容。
正确实现方案
调整AppLocalization类的定义,绑定泛型Builder类型,并修正State的泛型关联:
修正后的完整代码
typedef SimpleBuilder = Widget Function(BuildContext context, Object? object, Widget? child); typedef GenericsBuilder<GEN extends Object> = Widget Function(BuildContext context, GEN? object, Widget? child); class AppLocalization<RES extends Object> extends StatefulWidget { final Widget? child; // 替换为泛型Builder类型,与类的泛型参数RES绑定 final GenericsBuilder<RES>? builder; final Locale? defaultLocale; const AppLocalization({this.child, this.builder, this.defaultLocale, super.key}) : assert(builder != null || child != null); @override AppLocalizationState<RES> createState() => AppLocalizationState<RES>(); } // 显式指定State的泛型参数为AppLocalization<RES>,确保widget类型正确推断 class AppLocalizationState<RES extends Object> extends State<AppLocalization<RES>> { RES? _resources; @override void initState() { super.initState(); // 实际项目中若根据泛型创建实例,可省略as RES转换 _resources = AppResources() as RES; } @override Widget build(BuildContext context) { return widget.builder?.call(context, _resources, widget.child) ?? widget.child!; } }
使用代码无需修改
@override Widget build(BuildContext context) { return AppLocalization<AppResources>( builder: (context, res, child) => res == null ? const SizedBox.shrink() : const Text('hurray') ); }
关键要点
- 将
AppLocalization的builder字段类型改为GenericsBuilder<RES>,让Builder的参数类型与类的泛型参数RES强绑定,确保类型一致。 - 修正
AppLocalizationState的泛型继承为State<AppLocalization<RES>>,避免泛型信息丢失,保证widget的类型被正确推断。 - 初始化
_resources时,若实际是具体类型实例,需用as RES做显式转换(动态创建泛型实例的场景可省略)。
内容的提问来源于stack exchange,提问作者Martin Edlman
相关产品推荐
相关产品推荐

