这有点是我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>
有人可以帮我理解我做错了吗?
答案 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>{
…
}
通过此声明,您可以将带有错误的Temperament
和Show
的动物传递给特定的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
和DogTrainer
权限的动物(否则你不需要让它们成为类型参数)。
但如果您将DogTrainer<T extends Temperament, S extends Show>
extends Trainer<Dog<T,S>, DogTrainer.Trainables, T, S>
声明为TrainingAction
,则无法指定预期的Temperament
,因为它没有正确的Show
和TrainingAction
,这是无法解决,因为您希望enum
成为enums
。并且enum Trainables implements TrainingActions<Dog<?,?>>
只能使用通配符声明,就像使用enum
或只使用一种特定类型一样。内部static
始终为Trainer
,并且不能引用外部类类型参数。
所以这是总结的约束的组合:
A
包含参数animal T
和temperament S
并显示E
和培训操作A
T
应该为培训师S
和E
提供正确的A
应该对培训师E
enum
应为T
S
和E
使用不同类型的培训师,但enum
的常量类型(因为它是{{1}})这是不可能的。您当前的解决方案忽略约束 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;
}
...
}