【问题标题】:"Sets" of a particular enum type with nested generics具有嵌套泛型的特定枚举类型的“集合”
【发布时间】:2013-10-18 17:01:34
【问题描述】:

这在某种程度上是我对 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>

谁能帮我理解我做错了什么?

【问题讨论】:

  • 你能告诉我们错误是什么吗?
  • 刚刚添加了错误信息。

标签: java generics enums


【解决方案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> {
 …
}

但是,您的解决方案不再有效。使用此声明,您无法创建具有 TemperamentShow 的类型参数的 DogTrainer,除非按照预期将受过训练的动物声明为 Dog&lt;T,S&gt;,因为 Trainer 应该只训练具有正确 Temperament 的动物和Show(否则您不需要将它们设为类型参数)。

但是,如果您将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&lt;Dog&lt;?,?&gt;&gt; 所做的那样)或仅使用一种特定类型来声明。内部enums 始终为static,不能引用外部类类型参数。

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

  1. Trainer有参数动物A和气质T和显示S和训练动作E
  2. A 应该有正确的 TS 作为培训师
  3. E 应该有培训师的权利A
  4. E 应为 enum
  5. 您希望 TS 使用不同类型的不同训练器,但 E 使用常量类型(因为它是 enum

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

【讨论】:

    【解决方案2】:

    找出问题所在。我的具体教练需要定义如下:

    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;
      }
      ...
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-11
      • 1970-01-01
      相关资源
      最近更新 更多