2017-04-15 55 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 

但即使是在你的程序的情況下安全這種彎曲的類型擦除規則是不必要的。