2013-10-16 115 views
1

這是我的一個previous question的後續操作。具有嵌套泛型的特定枚舉類型的「集合」

比方說,我有一個動物的抽象父類。同一種動物可以有不同的氣質,可以在不同類型的表演中表演。所以,我的動物定義看起來是這樣的:

public abstract class Animal<T extends Temperament, S extends Show>{...} 

我想爲那些知道動物類型,氣質的各種動物,意式表演的動物是執行中的培訓師,並定義了一組技巧教練可以教那個動物。因爲我想設定一個特定的動物中定義的招數,我有一個枚舉界面如下:

public interface TrainingActions<T extends Animal<?,?>>{...} 

實現該接口定義了特定的動物一組的訓練動作,無論其氣質任何枚舉並且表明它可以在執行

牢記這些,我對父類培訓師的定義如下:

public abstract class Trainer 
    <A extends Animal<?,?>, 
    E extends Enum<E> & TrainingActions<A>, 
    T extends Temperament, 
    S extends Show>{ 
...} 

現在,我試圖創建一個具體的訓練器,但得到如下錯誤:

public class DogTrainer 
    <T extends Temperament, 
    S extends Show> extends Trainer 
    <Dog<T,S>, DogTrainer.Trainables, T, S>{//error right here 

    public enum Trainables implements TrainingActions<Dog<?,?>>{ 
    FETCH, GROWL, SIT, HEEL; 
    } 
    ... 
} 

我收到以下錯誤,試圖在我的DogTrainer定義中使用DogTrainer.Trainables作爲Trainer參數:

Bound mismatch: The type DogTrainer.Trainables is not a valid substitute 
for the bounded parameter <E extends Enum<E> & TrainingActions<A>> of the type 
Trainer<A,E,T,S> 

有人可以幫助我瞭解我在做什麼錯?

+2

您能告訴我們錯誤是什麼嗎? – hexafraction

+0

剛剛添加了錯誤消息。 – anishthecoder

回答

1

您通過添加到太多的約束到您通用簽名創建了一個無法解決的問題:我需要具體的教練,定義如下。與您的(假定)意圖相比,您目前的解決方案過於寬鬆。請看下面的聲明:

public abstract class Trainer 
    <A extends Animal<?,?>, // <- here you are not enforcing the right bounds 
    E extends Enum<E> & TrainingActions<A>, 
    T extends Temperament, 
    S extends Show>{ 
    … 
} 

您通過該聲明允許使用錯誤的TemperamentShow通過動物到特定Trainer實例。你最想要的是:

public abstract class Trainer 
<A extends Animal<T,S>, 
E extends Enum<E> & TrainingActions<A>, 
T extends Temperament, 
S extends Show> { 
… 
} 

但是,然後,你的解決方案不再工作了。有了這個聲明,你不能沒有,因爲它是因爲預期宣佈訓練有素的動物爲Dog<T,S>創造TemperamentShow一個DogTrainer有類型參數的Trainer應該訓練只動物的權利TemperamentShow(否則你不需要讓他們類型參數)。

但是如果你聲明DogTrainer作爲DogTrainer<T extends Temperament, S extends Show> extends Trainer<Dog<T,S>, DogTrainer.Trainables, T, S>你不能指定你打算TrainingAction,因爲它不具備正確的TemperamentShow因爲你想要的TrainingAction是一個enum這是不可能修復。並且enums只能使用通配符來聲明,例如您使用enum Trainables implements TrainingActions<Dog<?,?>>或者只使用一種特定類型。內部enum總是static並且不能引用外部類的類型參數。

因此,這是總結約束的組合:

  1. Trainer有參數動物A和氣質T並顯示S和培訓行動E
  2. A應該有一個教練的權利TS
  3. E應該有A的培訓師
  4. E應爲enum
  5. 要使用不同類型不同的訓練師TS但恆定的類型E(因爲它是一個enum

這是不可能的。您當前的解決方案忽略約束但沒有刪除至少一個約束,沒有解決方案

0

找出問題所在。

public class DogTrainer 
    <T extends Temperament, 
    S extends Show> extends Trainer 
    <Dog<?,?>, DogTrainer.Trainables, T, S>{// changed line 

    public enum Trainables implements TrainingActions<Dog<?,?>>{ 
    FETCH, GROWL, SIT, HEEL; 
    } 
    ... 
}