Dart:在泛型类模板中用命名构造函数实现多类反序列化
实现统一泛型序列化/反序列化列表的解决方案
你需要实现一套统一的泛型接口,处理Serializable子类的列表序列化与反序列化,避免为每种类型编写自定义列表反序列化逻辑,但当前代码因Dart不支持抽象静态方法、无法通过泛型类型直接调用构造函数而报错,以下是两种可行的解决方案:
方案一:给Schema传入反序列化工厂函数
通过将具体类型的反序列化逻辑(如User.fromMap)作为参数传入Schema,让Schema明确知晓如何将Map转换为对应对象,无需依赖抽象静态方法。
修正后的完整代码:
abstract class Serializable { // 仅保留序列化方法 Map<String, dynamic> toMap(); } class Schema<T extends Serializable> { // 存储当前类型的反序列化工厂函数 final T Function(Map<String, dynamic>) _fromMap; List<T> data = []; // 构造时传入对应类型的反序列化逻辑 Schema(this._fromMap); List<Map<String, dynamic>> serialize() { return data.map((e) => e.toMap()).toList(); } void deserialize(List<Map<String, dynamic>> inputData) { this.data = inputData.map(_fromMap).toList(); } } // 具体实现类 class User extends Serializable { String username; User(this.username); @override Map<String, dynamic> toMap() { return {'username': username}; } // 定义类型专属的反序列化工厂方法 factory User.fromMap(Map<String, dynamic> map) { return User(map['username'] as String); } } // 使用示例 void main() { final usersSchema = Schema<User>(User.fromMap); // 模拟从JSON解析得到的Map列表 final rawData = [{'username': 'alice'}, {'username': 'bob'}]; usersSchema.deserialize(rawData); print(usersSchema.data.map((u) => u.username)); // 输出: (alice, bob) }
方案优势:
- 逻辑直观,每个
Schema实例明确绑定对应类型的反序列化规则 - 无全局状态,避免类型冲突
- 符合依赖注入的设计思想
方案二:全局构造器注册器
如果需要集中管理所有Serializable类型的反序列化逻辑,可以通过静态注册中心存储类型与构造器的映射,Schema直接从注册中心获取反序列化方法,无需每次传入工厂函数。
完整代码示例:
abstract class Serializable { Map<String, dynamic> toMap(); // 全局注册中心:存储类型到反序列化构造器的映射 static final Map<Type, dynamic Function(Map<String, dynamic>)> _constructorRegistry = {}; // 注册类型的反序列化构造器 static void register<T extends Serializable>(T Function(Map<String, dynamic>) constructor) { _constructorRegistry[T] = constructor; } // 全局反序列化方法,根据类型匹配构造器 static T fromMap<T extends Serializable>(Map<String, dynamic> map) { final constructor = _constructorRegistry[T]; if (constructor == null) { throw StateError('Type $T has not been registered.'); } return constructor(map) as T; } } class Schema<T extends Serializable> { List<T> data = []; List<Map<String, dynamic>> serialize() { return data.map((e) => e.toMap()).toList(); } void deserialize(List<Map<String, dynamic>> inputData) { this.data = inputData.map((map) => Serializable.fromMap<T>(map)).toList(); } } // 具体实现类 class User extends Serializable { String username; User(this.username); @override Map<String, dynamic> toMap() { return {'username': username}; } factory User.fromMap(Map<String, dynamic> map) { return User(map['username'] as String); } } // 使用示例 void main() { // 提前注册User的反序列化构造器 Serializable.register(User.fromMap); final usersSchema = Schema<User>(); final rawData = [{'username': 'charlie'}, {'username': 'david'}]; usersSchema.deserialize(rawData); print(usersSchema.data.map((u) => u.username)); // 输出: (charlie, david) }
方案优势:
- 无需在创建
Schema时重复传入工厂函数 - 适合需要集中管理所有可序列化类型的场景
原代码的核心问题说明:
- Dart不支持抽象命名构造函数,也不允许子类重写父类的命名构造函数,因此原代码中
Serializable.fromMap作为抽象命名构造函数无效,子类的@override标注也是错误的。 - 泛型类型
T在运行时会被类型擦除,且T是Type类型而非具体实例,无法直接调用T.fromMap构造函数。
内容的提问来源于stack exchange,提问作者jarinox
相关产品推荐
相关产品推荐

