#json #http #dart #model
#json #http #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);
}
}
мой класс базовой модели таков:
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(), и я выполняю синтаксический анализ модели на основе типа модели, который я отправил в общий
я не знаю, возможно ли сделать некоторые общие ограничения, подобные этому, в dart, и мне нужно использовать FromJSON из этого типа, кто-нибудь знает, возможно ли это? или, если есть другое решение
Future<T> get<T extends BaseModel>(String url) {
Response response = await dio.get(url);
T.fromJson(response.body);
}
Ответ №1:
К сожалению, T.fromJson()
это невозможно. Обходным путем является поддержка фабрик для создания экземпляров.
Некоторые предостережения:
- Вы не можете отключить именованные конструкторы.
- Статические функции не наследуются, и нет способа требовать от подклассов их реализации.
- Наличие нестатической виртуальной функции from или create усложняет неизменяемые классы и код, не обнуляемый по умолчанию.
- Каждый применимый подкласс должен как реализовывать шаблон create или from, так и добавляться в factory map .
В целом, я думаю, было бы лучше передать полученный 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);
}