我正在研究一个流畅的API,并试图利用Java的泛型方法来提供一个优雅的API来处理我的用户的类型转换。由于类型擦除,我遇到了一些麻烦让它工作。如何为我的流利API构建一个接口层次结构?
这里是我的接口的简化版本,显示我运行到这个问题:
interface Query<T extends Query<T>> {
T execute();
Query<T> appendClause();
}
interface A<T extends A> extends Query<T> { }
class AImpl implements A<A> {
A execute() { ... }
Query<A> appendClause() { ... }
}
我对AImpl.appendClause()
得到一个错误。编译器说A
不在其范围内,应该扩展Query。据我所知,我的声明AImpl
implements A<A>
意味着A
确实延伸Query<A>
。
继另一个答案在这里,我试图通过改变AImpl
到分手任何可能无法解决的递归:
class AImpl implements A<AImpl> {
AImpl execute() { ... }
Query<AImpl> appendClause() { ... }
}
现在,我得到一个错误,编译A
,上面写着“类型参数T是不在其绑定” 。
有没有人对如何处理这个问题有任何建议? Java的泛型让我头疼。
编辑
我已经改变了A的定义
interface A<T extends A<T>> extends Query<T> { }
而这得到了第二次执行的AIMP1的工作。但我也想用用来查询的子类的能力扩展API:
interface B<T extends B> extends A<B> { }
class BImpl implements B<BImpl> {
BImpl execute() { ... }
Query<BImpl> appendClause() { ... }
}
这个定义让我的错误B
的声明:“类型参数B不是内的束缚,应延长”。
我可以b变更清理是错误
interface B<T extends B<T>> extends A<B<T>> { }
但现在我的接口定义也开始看起来很荒谬,我得到我做错了什么的感觉。另外,我仍然在BImpl中收到错误:“BImpl中的appendClause()无法在Query中实现appendClause();尝试使用不兼容的返回类型”。
关于如何清理我的子类定义的任何建议,所以我不需要指定extends
中的整个继承层次结构或我如何才能使BImpl工作?
EDIT 2
好吧,我遇到了另一个问题。我有一个生成的查询工厂类:
public class QueryFactory {
public static <T extends Query<T>> Query<T> queryForType(Class<T> type) { ... }
}
和客户端代码:
Query<B> bQuery = QueryFactory.queryForType(B.class);
我的客户端代码是给我的声明bQuery的错误:“类型参数‘B’不在范围它的约束;应该扩展'查询'“。我想在这一点上B均无扩展查询...
这个错误消失,如果我改变queryForType()调用
Query<? extends B> bQuery = QueryFactory.queryForType(B.class);
,但我仍然得到来自编译器的警告未检查:
unchecked method invocation: <T>queryForType(Class<T>) in QueryFactory is applied to Class<B>
unchecked conversion found: Query required: Query<B>
看起来类型擦除再次打我,但我不明白这些警告。还有什么建议让我回到正轨?谢谢!
编辑3
我可以得到它编译没有警告,如果我的客户端代码更改为
Query<BImpl> bQuery = QueryFactory.queryForType(BImpl.class);
但我真的很想从API的用户隐藏实现类。我试图让B成为一个抽象类,而不是一个接口,以防问题与此有关,但它没有帮助。
应该采取什么类型查询>代表?我认为签名没有意义。例如我希望一个'查询'返回'Apple'的实例,而不是'查询''为执行()'做的一个实例? –
Pyranja
苹果扩展查询。在这种情况下,execute()会返回一个Apple,并且您可以在Apple上调用appendClause()来查找更具体的Apple。 –
Greg
给你阅读这篇文章http://www.unquietcode.com/blog/2011/programming/using-generics-to-build-fluent-apis-in-java/ – cmbaxter