2017-04-15 30 views
0

我有两个抽象类: 集装箱,节点互补泛型类

一种容器总是包含相同类型的节点,以及一种节点将只属于其相应的容器: NodeTypeA存储在ContainerTypeA中,Node中没有其他的子类存储在它中。 NodeTypeB存储在ContainerTypeB中,Node中没有其他子类存储在其中。从Node到它的容器的反向引用也应该知道容器的类型,所以这个关系是双向的。

我在Java中实现这个问题。

我不喜欢这样写道:

Container<C extends Container<C,N>, N extends Node<C,N>> 
Node<C extends Container<C,N>, N extends Node<C,N>> 

然而,当我定义在容器中的以下字段,我得到一个错误:

private List<N> nodes; 

该错误消息说我应该代替n与节点。这对我来说似乎是多余的。为什么会发生这种情况,我怎么可以让程序知道,

N 

应该等于

Node<C,N> 

测试用例:

https://ideone.com/wam0gi

这背后的目的:

有许多不同种类的节点和许多不同的方式,他们可以互动。但是,他们有一些共同的主题。容器和节点应该是抽象类,我可以在其中定义方法和抽象方法来定义这些常见主题。 ContainerA和NodeA一起将定义一种特定的交互方法。我用这个仿制药,因为编程变得容易得多,如果我的IDE是足够聪明,知道在ContainerA任何节点总是在NodeA上,和NodeA上的主人总是一个ContainerA,所以我能避免一些不必要的类型转换。

(注:这个问题是类似的,但不等于Complementary generic types)从几个微不足道的错误(abstract

+2

什么是确切的错误信息?你能包括一个最小的,但完整的类,导致这个错误? – Thilo

+1

似乎很好:http://ideone.com/m1Qi2n。请构建一个[最小测试用例](http://stackoverflow.com/help/mcve)。 –

+0

最小测试用例:https://ideone.com/wam0gi –

回答

1

除了应先在Java classNode构造,错误类型的变量L 16行,尝试访问在第18行)的私人领域,你语义的问题是在管线18型thisNode<C,N>,不N

实现您的目标的一种方法是将抽象方法添加到Node,该方法返回N,所有子类将通过返回this来实现它。

abstract protected N me(); 

然后,一旦你添加适当的setter方法来Container,你会改变线路18

owner.add(me()); 
1

How can I get the program to understand that N should be equal to Node<C,N>

他们是不相等的。 N延伸Node<C, N>

private List<N> nodes; 

装置的Node<C, N>一些子类的列表。

您将难以添加到这样的列表。

考虑

List<N> nodes = ...; 

Node<C, N> node = new Node<>(...); 
nodes.add(node); // ERROR because node might not be the right subclass 

VS

List<Node<C, N>> nodes = ...; 

Node<C, N> node = new Node<>(...); 
nodes.add(node); // OK. 

VS

List<N> nodes = ...; 
N node = new Node<C, N>(...); // ERROR. Not all Node<C, N> are N 
// N is a sub-type not a super-type of Node<C, N> 
nodes.add(node); 

如果Node是最终的,你说这是不是 “””

There are many different kinds of Nodes

“””,那么你可以做

N node = (N) new Node<C, N>(..); // Unchecked conversion 

但即使是在你的程序的情况下安全这种弯曲的类型擦除规则是不必要的。