1

这在某种程度上是我之前提出的问题的后续。

假设我有一个动物的抽象父类。同一种动物可以有不同的气质,可以在不同类型的节目中表演。所以我的动物定义看起来像这样:

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用作参数时出现以下错误:TrainerDogTrainer

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>

有人可以帮我理解我做错了什么吗?

4

2 回答 2

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> {
 …
}

但是,您的解决方案不再起作用。使用此声明,您不能创建DogTrainer具有类型参数的对象,Temperament并且Show不按预期声明受过训练的动物,Dog<T,S>因为Trainer应该只训练具有正确Temperament和的动物Show(否则您不需要使它们成为类型参数)。

但是,如果您声明DogTrainerasDogTrainer<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<?,?>>或仅使用一种特定类型来声明。内部enums 总是static并且不能引用外部类类型参数。

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

  1. 具有Trainer参数动物A和气质T以及表演S和训练动作E
  2. A应该有权利TS教练
  3. E应该有A培训师的权利
  4. E应为enum
  5. 您需要具有不同类型的不同培训师,TS对于E(因为它是一个enum

这是不可能的。您当前的解决方案忽略了约束2,但如果不移除至少一个约束,则没有解决方案

于 2013-10-18T09:01:34.847 回答
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;
  }
  ...
}
于 2013-10-17T01:13:13.220 回答