Java &引用;套;具有特定枚举类型但具有泛型的
假设我有一个抽象类Java &引用;套;具有特定枚举类型但具有泛型的,java,generics,enums,Java,Generics,Enums,假设我有一个抽象类 public abstract class Trainer<T extends Animal>{} 公共抽象类培训师{} 我有专门的培训师,如: public DogTrainer extends Trainer<Dog>{} public HorseTrainer extends Trainer<Horse>{} 公共驯狗师扩展驯狗师{} 公共驯马师{} 每个“驯兽师”都有一套固定的技巧,他们可以训练动物去做,我想用Enum来做。
public abstract class Trainer<T extends Animal>{}
公共抽象类培训师{}
我有专门的培训师,如:
public DogTrainer extends Trainer<Dog>{}
public HorseTrainer extends Trainer<Horse>{}
公共驯狗师扩展驯狗师{}
公共驯马师{}
每个“驯兽师”都有一套固定的技巧,他们可以训练动物去做,我想用Enum来做。所以我有一个界面:
public interface TrainingActions<T extends Animal>{}
public <E extends Enum<?> & TrainingActions<T>> void add( E t ) {
completed.add( t );
}
公共接口培训动作{}
在每个培训师中,我都有一个实现此接口的枚举。因此:
public DogTrainer extends Trainer<Dog>{
public enum Trainables implements TrainingActions<Dog>{
BARK, BITE, ROLLOVER, FETCH;
}
}
public HorseTrainer extends Trainer<Horse>{
public enum Trainables implements TrainingActions<Horse>{
JUMP, TROT, REARUP;
}
}
公共驯狗师扩展驯狗师{
公共枚举可培训项实现培训操作{
树皮、咬、翻滚、取回;
}
}
公共驯马师{
公共枚举可培训项实现培训操作{
跳,小跑,重新站起来;
}
}
现在在每个培训师课程中,我想要一个名为“trainingComplete”的方法,该方法将一个枚举作为输入,并将其保存到一个集合中。所以
public DogTrainer extends Trainer<Dog>{
public enum Trainables implements TrainingActions<Dog>{
BARK, BITE, ROLLOVER, FETCH;
}
public Set<Trainables> completed = new HashSet<Trainables>();
public void trainingComplete(Trainables t){completed.add(t);}
}
公共驯狗师扩展驯狗师{
公共枚举可培训项实现培训操作{
树皮、咬、翻滚、取回;
}
public Set completed=新HashSet();
公共无效培训完成(培训内容t){completed.add(t);}
}
但是,我不想在每个特定的培训师中定义“completed”集,也不想在每个培训师中定义“trainingComplete”方法,而是想在父“Trainers”类中定义一些可以强制执行枚举类型的内容。。。所以它是枚举和泛型的奇怪组合
这可能吗?是的,您可以将您的
可培训内容
、设置完成
和培训完成(可培训内容t)
移动到课堂培训师处
这样你就不需要为每个驯狗师、驯马师编写这些代码了。。等等
abstract class Trainer<T extends Animal>{
public enum Trainables implements TrainingActions<Animal>{
BARK, BITE, ROLLOVER, FETCH;
}
public Set<Trainables> completed = new HashSet<Trainables>();
public void trainingComplete(Trainables t){completed.add(t);}
}
要指定接口的绑定并将其指定为枚举,需要一个通用交集,如下所示:
class MyClass<T extends Enum<T> & SomeInterface> {}
尽管进行了设计分析,但我认为最符合您的情况(最接近您已经创建的设计)的答案是:
- 您的
是DogTrainer.traineables
TrainingActions
- 您的
是驯马师.可培训人员
培训行动
可培训人员
已经是培训活动
因此,您可以只提供设置完成
,因为您已经在T
中有了您的动物信息:
abstract class Trainer<T extends Animal> {
Set<TrainingActions<T>> completed = new HashSet<TrainingActions<T>>();
public void add(TrainingActions<T> t ) {
completed.add( t );
}
}
如果确实要为接口强制执行枚举,请执行以下操作:
public interface TrainingActions<T extends Animal>{}
public <E extends Enum<?> & TrainingActions<T>> void add( E t ) {
completed.add( t );
}
public即使已经有了公认的答案,我也会将其发布以供进一步考虑
如果你阅读这个问题,考虑使用更松散的耦合元素,用聚合等代替高度特定和复杂的类型层次和泛型。
通过简单的聚合,您至少可以实现相同的类型&逻辑安全性,但松耦合设计。正如我在评论中提到的:
可能更好的是更多的收藏、拍卖等,以确保
同时输入安全性和弹性(不同的运动鞋具有不同的
在任何组合中对不同动物的能力,包括混合,
在某些情况下,不将一个人锁定为超级特定的培训大师
特定动物的超特异能力仅此而已
当然,我指的是“约翰能教马快跑,狗能教狗快跑”
“吠叫”,而不是“能教马或狗小跑或吠叫的约翰”
在每个声明中,Enum
应该是Enum
。啊,是=)thanx!更新显示的定义Animal@Bohemian,您能告诉我您需要在def中看到什么吗。关于动物?我想对于这个类比,它只是一些常见的动物特性(平均体重、属、种)和一些常见的方法。。。你打算把动物定义放在哪里?我想在父类的“动物”类中有一些可以执行枚举类型的东西
我想你的意思是我想在父类的***'Trainer'***类中有一些可以执行枚举类型的东西
,对吧?+1的答案很复杂,但这太棒了!这里的要点是将泛型参数绑定为两种类型的方法。你可以在任何你有控制权的地方应用这种技术。我感觉驯兽师中缺少了一个动物的类型参数。在OP的原始问题中,Trainer可以指动物的类型,但在您建议的方法中,我们不能(虽然在OP的示例代码中,它没有显示用法…),因此我认为它可能看起来像Trainer
,当然我指的是“John than可以教马小跑,教狗吠叫”
,而不是“约翰可以教马或狗小跑或吠叫”
。因此,我将介绍一些特定动物的训练技能,这些技能可以独立添加到教师中,甚至是一组更一般的技能(几乎所有我们可以教跑的动物).但这当然不是设计问题。要耐心。驯马师通常不会教马吠叫……他们可能会,但那是一匹奇数匹马。问题是,驯马师需要分开。因此这不是一个解决方案。我在过渡期间正是使用了这一策略=),但不幸的是,这并不能阻止某人吠叫rom将policydogtrainer的可训练性添加到PuppyTrainer中。@anishthecoder就像我在接受答案的评论中提到的那样-我认为问题不在于你说的话,但总体上不是最好的设计-指定policydogtrainer
等就像在OOP中进入最大的继承使用-你失去了太多的限制类型。我认为目前,应该有更简单的聚合等,而不是复杂的类型层次结构。你能给出一个工作示例吗?我有兴趣将你的解决方案与公认的答案进行比较。请看我的另一个回答。我没有确切或类似的实现。我只是在一般情况下提倡“组合优于继承”“。因为whuDogTrainer
不能同时是H
public class Dog extends Animal {
public enum BasicTrainables implements TrainingActions<Dog> {
SIT, COME, STAY, HEEL;
}
public enum IntermediateTrainables implements TrainingActions<Dog> {
BARK, BITE, ROLLOVER, FETCH;
}
public enum AdvacedTrainables implements TrainingActions<Dog> {
SNIFF_DRUGS, FIND_PERSON, ATTACK, GUARD;
}
};
public class PuppyTrainer extends Trainer<Dog, Dog.BasicTrainables> {}
public class ObedienceTrainer extends Trainer<Dog, Dog.IntermediateTrainables> {}
public class PoliceTrainer extends Trainer<Dog, Dog.AdvacedTrainables> {}
abstract class Trainer<T extends Animal> {
Set<TrainingActions<T>> completed = new HashSet<TrainingActions<T>>();
public void add(TrainingActions<T> t ) {
completed.add( t );
}
}
DogTrainer tr = new DogTrainer();
tr.add( DogTrainer.Trainables.BITE );
public <E extends Enum<?> & TrainingActions<T>> void add( E t ) {
completed.add( t );
}