具有继承和泛型的 Fluent API
我正在编写一个流畅的API来配置和实例化一系列“消息”对象。我有一个消息类型的层次结构。
为了能够在使用 fluent API 时访问子类的方法,我使用泛型来参数化子类,并使所有 fluent 方法(以“with”开头)返回泛型类型。请注意,我省略了流利方法的大部分主体;它们中进行了很多配置。
public abstract class Message<T extends Message<T>> {
protected Message() {
}
public T withID(String id) {
return (T) this;
}
}
具体子类以类似方式重新定义泛型类型。
public class CommandMessage<T extends CommandMessage<T>> extends Message<CommandMessage<T>> {
protected CommandMessage() {
super();
}
public static CommandMessage newMessage() {
return new CommandMessage();
}
public T withCommand(String command) {
return (T) this;
}
}
public class CommandWithParamsMessage extends
CommandMessage<CommandWithParamsMessage> {
public static CommandWithParamsMessage newMessage() {
return new CommandWithParamsMessage();
}
public CommandWithParamsMessage withParameter(String paramName,
String paramValue) {
contents.put(paramName, paramValue);
return this;
}
}
这个代码有效,即我可以实例化任何类并使用所有流畅的方法:
CommandWithParamsMessage msg = CommandWithParamsMessage.newMessage()
.withID("do")
.withCommand("doAction")
.withParameter("arg", "value");
以任何顺序调用流利的方法都是这里的主要目标。
但是,编译器警告所有操作都不安全。return (T) this
类型安全:未经检查的从“消息”到“T”的强制转换
我不确定如何重新组织层次结构以使此代码真正安全。即使它有效,以这种方式使用泛型感觉真的很复杂。特别是,我无法预见如果我忽略警告,运行时异常将发生的情况。将会有新的消息类型,因此我需要保持代码可扩展性。如果解决方案是完全避免继承,我也想获得替代方案的建议。
SO上还有其他问题可以解决类似的问题。它们指向一个解决方案,其中所有中间类都是抽象的,并声明了一个类似 的方法。尽管如此,最终它并不安全。protected abstract self()