json - Dart 中的通用约束
问题描述
我需要在 http 请求中抽象我的模型解析系统
我有一个 HttpClient 类
class HttpClient {
Dio dio = new Dio();
Future<T> get<T extends BaseModel>(String url) {
Response response = await dio.get(url);
T.fromJson(response.body);
}
}
我的 BaseModel 类是这样的:
abstract class BaseModel {
fromJson(Map<String, dynamic> json);
toJson();
}
和一个模型的例子:
class Person extends BaseModel {
String name;
String surname;
int age;
Person({this.name, this.surname, this.age});
Person.fromJson(Map<String, dynamic> json) {
// parse ToModel;
}
Map<String, dynamic> toJson() {
// parse toJson;
}
}
我想像这样使用我的 HttpClient:
class RandomClassToConsumeHttp {
HttpClient _httpClient;
Person person;
RandomClassToConsumeHttp(this._httpClient);
void _getPerson() async {
_person = await _httpClient.get<Person>("api/getPerson");
}
}
问题是:
我的 get 方法中有一个泛型,我需要泛型来扩展 BaseModel 类,所以我总是会有一个 fromJson() 的实现,并根据我发送给泛型的模型类型进行模型解析
我不知道是否可以在飞镖中做一些像这样的通用约束,我需要使用那种类型的 fromJson,有人知道它是否可能吗?或者如果有其他解决方案
Future<T> get<T extends BaseModel>(String url) {
Response response = await dio.get(url);
T.fromJson(response.body);
}
解决方案
不幸的是,T.fromJson()
这是不可能的。解决方法是维护工厂以创建实例。
一些警告是:
- 你不能撕掉命名的构造函数。
- 静态函数不是继承的,也没有办法要求子类来实现它们。
- 拥有非静态 virtual from或create函数会使不可变类和默认不可为空的代码复杂化。
- 每个适用的子类都需要实现create或from模式并添加到工厂映射中。
总而言之,我认为将收到的 json 传递给模型的构造函数会更好,例如:
var model = SomeModel.fromJson(httpClient.get('resource'));
最后,这是一个工厂实现示例:
abstract class Base {
static from(v) => SubA.from(v);
}
class SubA extends Base {
static from(v) => SubA();
}
class SubB extends Base {
static from(v) => SubB();
}
final _baseFromFactory = {
Base: Base.from,
SubA: SubA.from,
SubB: SubB.from,
// or you can do:
// SubB: (v) => /* create instance */
};
class Client {
get<T extends Base>(v) => _baseFromFactory[T](v);
// Alternatively, you can switch on T.
getAlt<T extends Base>(v) {
switch (T) {
case SubB: return SubB.from(v);
default: return SubA.from(v);
}
}
}
main() {
var client = Client();
var subA = client.get<SubA>('a value');
var subB = client.get<SubB>('a value');
var altA = client.getAlt<SubA>('a value');
var altB = client.getAlt<SubB>('a value');
print(subA);
print(subB);
print(altA);
print(altB);
}
推荐阅读
- wordpress - 如何修复安装在 bitnami magento 容器内的 wordpress 权限?
- c++ - 在“包装器”类中使用原子类型
- javascript - 在页面滚动上添加/删除导航对象类
- .net - 监听 Add_DocumentCompleted 事件 ShowDialog() 后仍然无法操作 DOM
- mysql - 找不到文件“./binlog.000007”(操作系统错误 2 - 没有这样的文件或目录)
- javascript - 实例成员在反应中不可访问
- r - R - 是否可以取消嵌套包含缺失 (NA) 值的列表列?
- python - 为什么即使我有日志文件,Tensorboard 也不显示任何图表?
- swift4 - /src:错误:找不到目标的源文件:MyKituraAppTests;使用 Swift 4 清单中的“路径”属性设置自定义目标路径
- python - Cython 多线程程序崩溃