You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现带工厂方法的抽象父类?泛型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;
}

使用步骤:

  1. 初始化时注册子类:
// 可以放在main函数或App初始化逻辑中
registerModel<ExtendedModel>(ExtendedModel.fromJson);
// 其他子类只需在此处添加注册即可
  1. 调用parse方法:
final json = {'id': 1, 'name': '测试'};
ExtendedModel model = parse<ExtendedModel>(json);

内容的提问来源于stack exchange,提问作者Sumit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 10:22:17