创建构造界面

Mic*_*ick 7 dart

几次,我遇到了一个用例,我需要为类本身的构造定义一个接口.一个这样的例子可能是,如果我想创建一个接口类,它定义了对象可以通过它自己序列化和反序列化的接口(用于输入到数据库,作为JSON发送等).你可能写这样的东西:

abstract class Serializable {
  String serialize();
  Serializable unserialize(String serializedString);
}
Run Code Online (Sandbox Code Playgroud)

但是现在你有一个问题,正如serialize()一个实例方法,unserialize()应该是一个静态方法(不可由Interface继承或强制执行)或构造函数(也不可继承).

这留下了一个状态,其中Serializable需要用于定义接口的类来定义serialize()方法,但是没有办法要求这些类定义static unserialize()方法或Foo.fromSerializedString()构造函数.

如果您创建unserialize()实例方法,那么反序列化实现类Foo将如下所示:

Foo foo = new Foo();
foo = foo.unserialize(serializedString);
Run Code Online (Sandbox Code Playgroud)

这是相当繁琐和丑陋的.

我能想到的唯一另一个选择是在Serializable接口中添加一个注释,要求很好地实现类定义适当的静态方法或构造函数,但如果开发人员错过它并且还会损害代码完成,这显然很容易出错.

那么,有更好的方法吗?是否存在一些模式,您可以通过这种模式强制实现类来定义构建自身的方法,或者提供一般效果的方法?

Pix*_*ant 3

如果您想要继承保证,则必须使用实例方法。不过,通过使用反射,您可以做得比手动实例化更好一些。

abstract class Serializable {

  static Serializable fromSerializedString(Type type, String serializedString) {
    ClassMirror cm = reflectClass(type);
    InstanceMirror im = cm.newInstance(const Symbol(''), []);
    var obj = im.reflectee;
    obj.unserialize(serializedString);
    return obj;
  }

  String serialize();
  void unserialize(String serializedString);
}
Run Code Online (Sandbox Code Playgroud)

现在,如果有人实现,Serializable他们将被迫提供反序列化方法:

class Foo implements Serializable {

  @override
  String serialize() {
    // TODO: implement serialize
  }

  @override
  void unserialize(String string) {
    // TODO: implement unserialize
  }
}
Run Code Online (Sandbox Code Playgroud)

你可以得到一个像这样的实例:

var foo = Serializable.fromSerializedString(Foo, 'someSerializedString');
Run Code Online (Sandbox Code Playgroud)

这可能比手动方法更漂亮、更自然,但请记住,它使用反射来解决所有可能带来的问题。

如果您决定使用静态方法和警告注释,那么提供一个自定义转换器可能会有所帮助,该转换器会扫描所有实现可序列化的类,并警告用户或停止构建(如果有任何类没有相应的静态反序列化)方法或构造函数(类似于 Polymer 的工作方式)。这显然不会提供编辑器可以使用实例方法提供的即时反馈,但比文档中的简单注释更明显。