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

3z6pesqy  于 2023-06-27  发布在  其他
关注(0)|答案(3)|浏览(109)

我想在一个抽象类中声明,但不是定义一个工厂构造函数。
在我的例子中,我想创建一个方法,它接受任何实现String toJson()方法和fromJson(Map<String, dynamic> data)工厂构造函数的类。
有没有办法在Dart中实现这一点?我正在寻找类似以下的内容,这不是有效的Dart代码:

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

wpcxdonn1#

恐怕事情不会如你所愿。
构造函数不是接口的一部分。他们的行为更像是静态成员。因此,您不能向接口添加工厂,并且代码也没有任何方法来调用工厂构造函数,因为给定了一个扩展此类型的类型变量。
因此,由于构造函数不能是接口的一部分,因此构造函数也不能是抽象的。抽象仅仅意味着“使成员成为接口的一部分,但不向类中添加实现”。
你可以将工厂声明为一个普通的方法,但是只有当你已经有了一个示例的时候才能调用它,这可能不是你想要的构造函数。
传递 * 代码 * 的唯一方法是作为函数或带方法的对象。所以,如果你想用JsonSerializable类型参数化某个对象,并且你想创建这样一个对象,你需要传递一个工厂 * 函数沿着:

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

你可以用以下方式来称呼它:

var myValue = deserialize(jsonString, (x) => MyClass.fromJson(x));

(If MyClass.fromJson是一个静态函数,而不是构造函数,你可以只写deserialize(jsonString, MyClass.fromJson),但Dart还没有构造函数的撕裂)。

mkshixfv

mkshixfv2#

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

事实证明,这比直接在类上使用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>

46qrfjad

46qrfjad3#

下面是一个使用Firestore DocumentSnapshot对象的抽象方法,其中factory作为Function(引用)参数传递。* 感谢之前的回答 *

class User extends BaseModel {
  User({
    String? docId,
    required this.userId,
  })  : super(docId: docId);

  final String this.userId;    

  factory User.fromFirestoreDoc(DocumentSnapshot<Map<String, dynamic>> doc,) {
    final value = BaseModel.getModel(doc, User.fromJson);
    return value;
  }

  factory User.fromJson(Map<String, dynamic> json) {
    return User(
      docId: json['docId'],
      userId: json['userId'],
    );
  }
}

基础类:

class BaseModel {
  BaseModel({String? docId}) {
    if (docId != null) {
      this.docId = docId;
    }
  }

  String docId = 'NotSet';

  static dynamic getModel(
    DocumentSnapshot<Map<String, dynamic>> doc,
    Function(Map<String, dynamic>) fromJsonHandler,
  ) {
    final json = BaseModel._getAsDocJson(doc);
    if (json == null) {
      throw Exception('No data for fromJsonHandler: $fromJsonHandler');
    }

    return fromJsonHandler(json);
  }

  static Map<String, dynamic>? _getAsDocJson(
      DocumentSnapshot<Map<String, dynamic>> doc) {
    final json = doc.data();
    if (json != null) {
      json['docId'] = doc.id;
    }

    return json;
  }
}

相关问题