如何实现带工厂方法的抽象父类?泛型JSON解析报错解决
问题解决:Dart泛型方法中调用子类的fromJson工厂构造
问题根源
你遇到的报错是因为泛型类型参数T是一个Type对象,而非具体的类实例,Dart不允许直接通过Type对象调用类的静态方法或工厂构造函数。同时,你尝试的实例方法fromJson需要先有实例才能调用,这和parse方法创建实例的需求矛盾;而条件判断的方式又违反了开闭原则,新增子类时必须修改parse方法。
解决方案
以下是两种优雅的实现方式,无需重复编写类型判断:
方案一:传递构造器函数(最直接、类型安全)
修改parse方法,让它接收一个创建实例的函数参数,直接复用子类的fromJson工厂构造:
class MasterModel { MasterModel(); factory MasterModel.fromJson(Map<String, dynamic> json) => MasterModel(); } class ExtendedModel extends MasterModel { int id; String name; ExtendedModel(this.id, this.name); factory ExtendedModel.fromJson(Map<String, dynamic> json) => ExtendedModel(json['id'], json['name']); } // 泛型parse方法,接收构造器函数作为参数 T parse<T extends MasterModel>(Map<String, dynamic> json, T Function(Map<String, dynamic>) createFromJson) { return createFromJson(json); }
调用示例:
final json = {'id': 1, 'name': '测试'}; ExtendedModel model = parse<ExtendedModel>(json, ExtendedModel.fromJson);
方案二:类型注册表(无需重复传参,适合多子类场景)
通过全局注册表维护类型与构造器的映射,parse方法根据类型自动获取对应的构造器:
class MasterModel { MasterModel(); factory MasterModel.fromJson(Map<String, dynamic> json) => MasterModel(); } class ExtendedModel extends MasterModel { int id; String name; ExtendedModel(this.id, this.name); factory ExtendedModel.fromJson(Map<String, dynamic> json) => ExtendedModel(json['id'], json['name']); } // 全局注册表:存储类型对应的构造器 final Map<Type, MasterModel Function(Map<String, dynamic>)> _modelConstructors = {}; // 注册子类构造器的方法(可在App初始化时统一调用) void registerModel<T extends MasterModel>(T Function(Map<String, dynamic>) constructor) { _modelConstructors[T] = constructor; } // 泛型parse方法 T parse<T extends MasterModel>(Map<String, dynamic> json) { final constructor = _modelConstructors[T]; if (constructor == null) { throw Exception('未注册类型 $T 的构造器,请先调用registerModel注册'); } return constructor(json) as T; }
使用步骤:
- 初始化时注册子类:
// 可以放在main函数或App初始化逻辑中 registerModel<ExtendedModel>(ExtendedModel.fromJson); // 其他子类只需在此处添加注册即可
- 调用
parse方法:
final json = {'id': 1, 'name': '测试'}; ExtendedModel model = parse<ExtendedModel>(json);
内容的提问来源于stack exchange,提问作者Sumit
相关产品推荐
相关产品推荐

