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

Dart中抽象类工厂构造函数编写及泛型类调用问题

问题

我想要编写一个泛型类Repository,它接收泛型参数T并从JSON(Map<String, dynamic>)构建T实例。为此我定义了抽象类JsonSerializable:

abstract class JsonSerializable {
  String toJson();
  JsonSerializable.fromJson(Map<String, dynamic> json);
}

接着创建了继承JsonSerializable的Item类(任何要作为Repository泛型参数的类都需如此):

class Item extends JsonSerializable {
  Item.fromJson(super.json) : super.fromJson();

  @override
  String toJson() {
    // TODO: implement toJson
    throw UnimplementedError();
  }
}

Repository类代码如下:

class Repository<T extends JsonSerializable> {
  const Repository();

  Future<T> getIdFromJson(Map<String, dynamic> json) async {
    return T.fromJson(json)['id'];
  }
}

但出现编译错误:

The method 'fromJson' isn't defined for the type 'Type'.
Try correcting the name to the name of an existing method, or defining a method named 'fromJson'.

我尝试将Item类的extends改为implements:

class Item implements JsonSerializable {
  const Item();

  @override
  factory Item.fromJson(Map<String, dynamic> json) {
    return const Item();
  }

  @override
  String toJson() {
    throw UnimplementedError();
  }
}

但仍出现相同错误。我是Dart/Flutter新手,请问该如何修改以实现所需功能?

解决方法

Dart中无法直接通过泛型类型T调用构造方法,因为泛型在运行时会被类型擦除,编译器无法确认T必然包含fromJson构造方法。以下是具体修改方案:

1. 重构Repository类,传入构造器函数

给Repository添加一个构造参数,用来接收T的实例创建逻辑,绕过泛型类型擦除的限制:

class Repository<T extends JsonSerializable> {
  // 接收一个能从Map创建T实例的函数
  final T Function(Map<String, dynamic>) createFromJson;

  const Repository(this.createFromJson);

  // 修正方法:先创建实例,再获取id
  Future<String> getIdFromJson(Map<String, dynamic> json) async {
    T instance = createFromJson(json);
    return instance.id;
  }
}

2. 完善抽象类与子类实现

为确保所有JsonSerializable子类都有id属性,在抽象类中添加抽象 getter:

abstract class JsonSerializable {
  String get id;
  String toJson();
}

子类用extends实现

class Item extends JsonSerializable {
  @override
  final String id;

  Item.fromJson(Map<String, dynamic> json) : id = json['id'] as String;

  @override
  String toJson() {
    return '{"id": "$id"}';
  }
}

子类用implements实现

class Item implements JsonSerializable {
  @override
  final String id;

  const Item(this.id);

  factory Item.fromJson(Map<String, dynamic> json) {
    return Item(json['id'] as String);
  }

  @override
  String toJson() {
    return '{"id": "$id"}';
  }
}

3. 使用Repository的示例

创建Repository实例时,传入子类的fromJson构造方法:

void main() async {
  final itemRepo = Repository<Item>(Item.fromJson);
  final json = {'id': '123'};
  String itemId = await itemRepo.getIdFromJson(json);
  print(itemId); // 输出123
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 18:03:32