如何在抽象类中声明工厂构造函数?

时间:2019-06-06 20:02:45

标签: dart

我想声明,但不想在抽象类中定义工厂构造函数。

就我而言,我想创建一个方法,该方法可以接受实现String toJson()方法以及fromJson(Map<String, dynamic> data)工厂构造函数的任何类。

在Dart中有什么方法可以实现? 我正在寻找类似以下内容的东西,它不是有效的Dart代码:

abstract class JsonSerializable {
  factory fromJson(Map<String, dynamic> data);
  String toJson();
}

2 个答案:

答案 0 :(得分:4)

恐怕无法按照您想要的方式工作。

构造函数不是接口的一部分。他们的行为更像静态成员。 因此,您不能在接口中添加工厂,并且给定类型变量来扩展该类型,代码也将无法调用工厂构造函数。

因此,由于构造函数不能为接口的一部分,因此构造函数也不能为抽象。抽象是简单地表示“使成员成为接口的一部分,但没有将实现添加到类中”。

您可以将工厂声明为普通方法,但是只有当您已有实例时才可以调用它,而这可能不是构造函数所要的。

传递 code 的唯一方法是使用函数或带有方法的对象。因此,如果您想通过JsonSerializable类型的参数化某些东西,并且希望能够创建这样的对象,则需要传递一个工厂 function

T deserialize<T extends JsonSerializable>(
    String json, T factory(Map<String, dynamic> data) {
   return factory(jsonParse(json) as Map<String, dynamic>);
}

答案 1 :(得分:2)

正如接受的答案所建议,我最终创建了一个Serializer<T>类型,该类型由序列化程序为每个类实现:

enter image description here

事实证明,与仅在类上直接使用toJson / fromJson相比,这有很多好处:

  • 它使序列化逻辑与实际类分离。这意味着更好的代码可读性,因为类仅包含与类直接相关的方法-序列化器甚至可以放入其自己的文件中。
  • 当前,扩展无法创建构造函数。因此,单独使用序列化程序可以为现有类(例如String或Flutter的Color)编写序列化程序,而您不能在其中添加fromColor构造函数。
  • 这两点结合在一起,也意味着它也可以很好地与代码生成配合使用-类是手写的,序列化器可以在单独的文件中生成。

代码示例:

class Fruit {
  Fruit(this.name, this.color);

  final String name;
  final String color;
}

// in another file

class FruitSerializer extends Serializer<Fruit> {
  Map<String, dynamic> toJson(Fruit fruit) {
    return ...;
  }

  Fruit fromJson(Map<String, dynamic> data) {
    return Fruit(...);
  }
}

然后还将序列化器传递给需要它的代码:

someMethod<T>(Serializer<T> serializer, T value) {
  ...
}

someMethod(FruitSerializer(), someFruit);
final fruit = recreateFruit(FruitSerializer());

很明显,您不能将无法序列化的对象传递给代码,因为该方法需要Serializer<T>