使用嵌套泛型“设置”特定枚举类型

时间:2013-10-16 23:56:02

标签: java generics enums

这有点是我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.Trainables的定义中尝试使用Trainer作为DogTrainer的参数时出现以下错误:

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 个答案:

答案 0 :(得分: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> {
 …
}

但是,你的解决方案不再适用了。使用此声明,您无法为DogTrainerTemperament创建Show类型参数,而无需将受过训练的动物声明为Dog<T,S>,因为Trainer应该Temperament只训练具有ShowDogTrainer权限的动物(否则你不需要让它们成为类型参数)。

但如果您将DogTrainer<T extends Temperament, S extends Show> extends Trainer<Dog<T,S>, DogTrainer.Trainables, T, S>声明为TrainingAction,则无法指定预期的Temperament,因为它没有正确的ShowTrainingAction,这是无法解决,因为您希望enum成为enums。并且enum Trainables implements TrainingActions<Dog<?,?>>只能使用通配符声明,就像使用enum或只使用一种特定类型一样。内部static始终为Trainer,并且不能引用外部类类型参数。

所以这是总结的约束的组合:

  1. A包含参数animal T和temperament S并显示E和培训操作A
  2. T应该为培训师SE提供正确的
  3. A应该对培训师
  4. 拥有正确的E
  5. enum应为T
  6. 您希望SE使用不同类型的培训师,但enum的常量类型(因为它是{{1}})
  7. 这是不可能的。您当前的解决方案忽略约束 2 ,但没有删除至少一个约束就没有解决方案

答案 1 :(得分: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;
  }
  ...
}