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
相关产品推荐
相关产品推荐

