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中进入最大的继承使用-你失去了太多的限制类型。我认为目前,应该有更简单的聚合等,而不是复杂的类型层次结构。你能给出一个工作示例吗?我有兴趣将你的解决方案与公认的答案进行比较。请看我的另一个回答。我没有确切或类似的实现。我只是在一般情况下提倡“组合优于继承”“。因为whu
DogTrainer
不能同时是
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 );
}