几乎循环类型绑定的java递归类型参数
我有以下两个接口:
/**
* A marker interface to denote that an object implements a view on some other object.
*
* @param <T> The type of object that is viewed
*/
public interface View<T extends Viewable<View<T>>> {
}
/**
* An interface for objects that are viewable via a view.
*
* @param <T> The type of viewable object
*/
public interface Viewable<T extends View<?>> {
public void addViewCallback(final T view);
public void removeViewCallback(final T view);
}
我想强制执行以下内容:
View
(称为(a))的类型参数应该是查看该视图(a)的Viewable
李>Viewable
(称为(b))的类型参数应该是aView
,它可以通过相同的可视对象(b)进行查看李>
我想我已经为View
完成了边界,但是我要如何使它们为Viewable
工作呢?我现在得到的东西可以编译,但不能提供足够的保护
到目前为止,我无法制定一些我不想要的被接受的东西,但是我可以制定我做想要的东西,如果这有帮助的话:
public class Hand implements Viewable<HandView>
public interface HandView extends View<Hand>
# 1 楼答案
这对我来说唯一有效的方法是同时指定视图和可查看类型参数:
public interface View<VB extends Viewable<VB,T>, T extends View<VB,T>>
public interface Viewable<VB extends Viewable<VB,T>, T extends View<VB,T>>
请记住,这将要求您创建特定的接口:
public interface Hand implements Viewable<Hand,HandView>
public interface HandView extends View<Hand,HandView>
# 2 楼答案
由于您的
View
是一个标记接口,而且到目前为止,您还没有制定出任何您不想要的被接受的东西,因此我对View
接口的使用提出了完全的质疑。你对自己施加了不必要的限制,只会带来麻烦简化
# 3 楼答案
我设法让它工作,同时考虑了这里的所有其他答案
似乎@Joffrey's answer让我开始了不少,但后来我意识到,这种方式根本不可能,因为方法参数不能是协变的
我也同意,这可能是太多的工作,但这就是为什么它是一些实验性的东西,在工作时间紧迫的情况下,在浪费时间之前,我可能会三思而后行
可能的解决办法之一是:
实施示例:
# 4 楼答案
正如@SimonAndréForsberg所讨论的那样,过于保守的编程往往是不必要的时间浪费,我们应该相信自己的声明
然而,为了好玩,这里有一个解决方案,可以在编译时强制执行您想要的对类/接口声明的所有限制
声明
View
接口:这里,我们只想确保类型参数是
Viewable
第二个类型参数不需要限制,因为
Viewable
的声明不允许Viewable<T,?>
存在,如果?
本身不是View<T>
{}接口:
T
需要声明为Viewable
,因为我们在行尾将它用作View<T>
的类型参数李>?
进行任何限制,因为在这之后,如果第一个类型参数是T
,则第二个类型参数需要是View<T>
李>用法