如何在飞镖中使用多态

时间:2020-09-24 23:48:23

标签: flutter dart

嗨,我需要在Flutter中使用多态性,才能将其用于从Restfull API获取数据 但这不起作用。

首先我有一个基类(模型)

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

}

然后我派生了班(城市)

class City extends  Model {

  int id;
  String name;
  List<Region> regions;

  City({this.id, this.name, this.regions});

  City.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    name = json['name'];
    if (json['regions'] != null) {
      regions = new List<Region>();
      json['regions'].forEach((v) {
        regions.add(new Region.fromJson(v));
      });
    }
  }
}

这是带有getAllModel方法的函数

class Repository
{
  static Future<List<T>> getAllModel<T extends Model>( apis url) async {
    try {
      bool tk = await Cache.tokenExists();
      if (tk) {
        String token = await Cache.getString(keys.api_token);
        var body = {};
        List<dynamic> data = await Request.callAPI(
            apiName.name(url),
            body,
            method: 'GET', apiToken: token);

        List<T> objs = new List();

        if (data != null) if (data.length > 0) {
          data.forEach((v) {

           T r = Model.fromJson(v) as T;
            objs.add(r);
          });
          return objs;
        }
        return objs;
      }
      return new List();
    } catch (e, stacktrace) {
      print("getAll() | catch exception");
      print(e);
      print(stacktrace);
      return new List();
    }
  }
  
}

最后这是一个调用方法

static Future<List<City>> getCities() async {
        return Repository.getAllModel(apis.getCities);
  }

这是个问题

类型'模型'不是类型转换中类型'城市'的子类型

我该如何解决?

1 个答案:

答案 0 :(得分:0)

Model.fromJson(v)将始终返回基本类型Model的值。

您不能在此处将其强制转换为T = City

T r = Model.fromJson(v) as T;

因为Dart不知道如何将Model变成City

可以这么说,您想称呼“ T.fromJson(v)”,但是叫Dart doesn't allow us to speak polymorphically about constructors

我认为您最好的选择是将相关的fromJson函数传递给getAllModel

// The type of functions that take a JSON map and return T.
typedef JsonDecoder<T> = T Function(Map<String, dynamic> json);

// Use a provided `fromJson` callback to transform your API results:
Future<List<T>> getAllModel<T extends Model>(String url,
                                             JsonDecoder<T> fromJson) async {
  ...
  T r = fromJson(v);
  ...
}

// And provide it like so:
void myFunction() {
  final cities = await getAllModel<City>("city url", (j) => City.fromJson(j));
}

(有点令人讨厌的是,我们can't even write this:)

getAllModel<City>("city url", City.fromJson);
                              ^^^^^^^^^^^^^

顺便说一句,我建议您调查json_serializable