34

抽象クラスがあるとしましょう

public abstract class Trainer<T extends Animal>{}

私は次のような特定のトレーナーを持っています:

public DogTrainer extends Trainer<Dog>{}
public HorseTrainer extends Trainer<Horse>{}

これらの「トレーナー」のそれぞれには、動物を訓練できる一連の固定されたトリックがあり、これには Enum を使用したいと考えています。だから私はインターフェースを持っています:

public interface TrainingActions<T extends Animal>{}

各トレーナーには、このインターフェースを実装する Enum があります。そう:

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

各トレーナー クラスで、Enum の 1 つを入力として受け取り、それをセットに保存する「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);}
}

ただし、特定の各トレーナーで「完了」セットを定義し、各トレーナーで「trainingComplete」メソッドを定義する代わりに、親の「トレーナー」クラスに、列挙型を適用できる何かが必要です...つまり、列挙型とジェネリックの奇妙な組み合わせです。

これは可能ですか?

4

4 に答える 4

1

設計分析にもかかわらず、最も状況に応じた (作成済みの設計に最も近い) 答えは次のとおりだと思います。

  • あなたDogTrainer.TrainablesTrainingActions<Dog>
  • あなたHorseTrainer.TrainablesTrainingActions<Horse>

一般的に、あなたTrainablesはすでにTrainingActions<T extends Animal>

に動物の情報が既にSet<TrainingActions<T>> completedあるため、を指定するだけで済みます。T

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 );

インターフェースに Enum を強制したい場合は、次のようにします。

public <E extends Enum<?> & TrainingActions<T>> void add( E t ) {
   completed.add( t );
}
于 2013-10-11T12:14:55.723 に答える
-2

はい、あなたTrainablesSet<Trainables> completedtrainingComplete(Trainables t)をクラス トレーナーに移動できます。

こうすれば、DogTrainer、HorseTrainer などごとにこれらのコードを記述する必要がなくなります...

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

それ以外の場合は、trainingComplete(Trainables t) を抽象化し、各トレーナー実装クラスに実装する必要があります。

abstract class Trainer<T extends Animal>{
     public enum Trainables implements TrainingActions<Animal>{
            BARK, BITE, ROLLOVER, FETCH;
     }
      public Set<Trainables> completed = new HashSet<Trainables>();
      abstract public void trainingComplete(Trainables t);
}

これで、DogTrainer と HorseTrainer が実装されますtrainingComplete(Trainables t)

 public class DogTrainer extends Trainer<Dog>{      
     public void trainingComplete(Trainables t){
          completed.add(t);
     }
 }

 public class HorseTrainer extends Trainer<Horse>{     
     public void trainingComplete(Trainables t){
           completed.add(t);
     }
 }
于 2013-10-11T03:53:41.153 に答える