几次,我遇到了一个用例,我需要为类本身的构造定义一个接口.一个这样的例子可能是,如果我想创建一个接口类,它定义了对象可以通过它自己序列化和反序列化的接口(用于输入到数据库,作为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接口中添加一个注释,要求很好地实现类定义适当的静态方法或构造函数,但如果开发人员错过它并且还会损害代码完成,这显然很容易出错.
那么,有更好的方法吗?是否存在一些模式,您可以通过这种模式强制实现类来定义构建自身的方法,或者提供一般效果的方法?
如果您想要继承保证,则必须使用实例方法。不过,通过使用反射,您可以做得比手动实例化更好一些。
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 的工作方式)。这显然不会提供编辑器可以使用实例方法提供的即时反馈,但比文档中的简单注释更明显。
| 归档时间: |
|
| 查看次数: |
712 次 |
| 最近记录: |