2013-08-28 3 views
1

Моя цель довольно проста. У меня есть SetInterface<T>:Java - общий подстановочный вопрос

public interface SetInterface<T> 
{ 
    public T duplicateSet(); 
} 

Я тогда также иметь ExerciseInterface <T extends SetInterface<?>>

public interface ExerciseInterface <T extends SetInterface<?>> 
{ 
    public T getSet(int pos); 
    public void addSet(T set); 
} 

Все здорово работает на этой точке.

Проблема возникает, когда я пытаюсь создать коллекцию Generic, содержащую разные классы, которые все реализуют ExerciseInterface.

Я довольно новичок в Generics, и я продолжаю думать, что я решил что-то, но все, что я делаю, это толкать ошибку.

Проблема в значительной степени суммируется моей addA() и addB() методы

public class Workout { 

    private String name; 
    private List <? extends ExerciseInterface<SetInterface<?>>> exerciseList; 

// Constructor 
public Workout(String name) 
{ 
    this.name = name; 
    exerciseList = new ArrayList<ExerciseInterface<SetInterface<?>>>(); 
} 

public String getName() { 
     return name; 
    } 

public void setName(String name) { 
     this.name = name; 
    } 

public void addExerciseA(ExerciseInterface<SetInterface<?>> exercise { 
     exerciseList.add(exercise); 
    } 

public <T extends ExerciseInterface<SetInterface<?>>> void addExerciseB(T exercise { 
     exerciseList.add(exercise); 
    } 

public ExerciseInterface<SetInterface<?>> getExercise(int pos) { 
     return exerciseList.get(pos); 
    } 
} 

Первый add() выдает следующую ошибку ..

The method add(capture#2-of ? extends ExerciseInterface<SetInterface<?>>) in the type List<capture#2-of ? extends ExerciseInterface<SetInterface<?>>> is not applicable for the arguments (ExerciseInterface<SetInterface<?>>) 

Второго add() дает эту ошибку ..

The method add(capture#2-of ? extends ExerciseInterface<SetInterface<?>>) in the type List<capture#2-of ? extends ExerciseInterface<SetInterface<?>>> is not applicable for the arguments (ExerciseInterface<SetInterface<?>>) 

Просто для восстановления У меня есть SetInterface, который реализует различные типы наборов.

У меня также есть разные упражнения, которые отражают наборы. Например:

BodyWeightExercise implements <SetInterface<BodyweightSet>> 

и

WeightsExercise implements <SetInterface<WeightsSet>> 

Так что моя цель состоит в том, чтобы иметь набор различных упражнений и метод, который позволяет мне добавить к этой коллекции.

Любая помощь была бы искренне оценена, я уже потерял несколько волос.

Cheers.

EDIT: Если это не выполнимо, любые указатели в более приемлемом направлении будут оценены только по достоинству.

EDIT2: Я изменил список на List <ExerciseInterface<SetInterface<?>>> exerciseList;, и ошибка в методах add() исчезла.

Однако, используя этот тестовый код ..

WeightsSet weightsSet = new WeightsSet();  
WeightsExercise weightsExercise = new WeightsExercise(); 

weightsExercise.addSet(weightsSet); 

Workout workout = new Workout("Wok"); 
workout.addExerciseA(weightsExercise);  <-- ERROR 

Я пытаюсь добавить WeightsExercise в Список тренировки, но я получаю эту ошибку сейчас ..

Bound mismatch: The generic method addExerciseB(T) of type Workout is not applicable for the arguments (WeightsExercise). The inferred type WeightsExercise is not a valid substitute for the bounded parameter <T extends ExerciseInterface<SetInterface<?>>> 

РЕДАКТИРОВАТЬ 3: Примеры классов, простирающиеся ExerciseInterface и SetInterface (конкретные методы обновления в интерфейсах выше, а)

public class WeightsExercise implements ExerciseInterface<SetInterface<WeightsSet>> 
{ 
@Override 
public SetInterface<WeightsSet> getSet(int pos) {return null;} 

@Override 
public void addSet(SetInterface<WeightsSet> set) {} 
} 

public class WeightsSet implements SetInterface<WeightsSet> 
{ 
@Override 
public WeightsSet duplicateSet() {return null;} 
} 

РЕШИТЬ: Это решение кажется правильно включать в себя все.

public class Workout 
{ 
private String name; 
private List <ExerciseInterface<? extends SetInterface<?>>> exerciseList; 

// Constructor 
public Workout(String name) 
{ 
    this.name = name; 
    exerciseList = new ArrayList<ExerciseInterface<? extends SetInterface<?>>>(); 
} 

public String getName()                   {return name;} 
public void setName(String name)                {this.name = name;} 
public void addExerciseA(ExerciseInterface<? extends SetInterface<?>> exercise)     {exerciseList.add(exercise);} 
public ExerciseInterface<? extends SetInterface<?>> getExercise(int pos)      {return exerciseList.get(pos);} 

}

+0

Вы не можете добавить что-то вы не знаете тип. –

+0

Итак, у вас есть предложение о том, как создать коллекцию, содержащую кучу классов, расширяющих ExerciseInterface ? – mgibson

+0

Вы должны показать нам, как выглядят ваши классы. 'WeigthsSet',' WeightsExercise'. Не ясно. –

ответ

2

Вы должны изменить список вашей декларацию:

List<ExerciseInterface<SetInterface<?>>> exerciseList; 

При использовании верхнего ограниченных символов, которые я не думаю, что вам действительно нужно здесь, вы не можете добавить что-либо в списке, кроме null, и элементы, ранее извлеченные из него.

Это потому, что вы точно не знаете, какой конкретный параметризованный тип списка он действительно ссылается. Например, для: List<? extends CharSequence> можно указать ArrayList<String> или ArrayList<StringBuffer>. Таким образом, вы не можете добавить ничего в этот список, потому что это не безопасный тип. Возможно, вы добавите объект StringBuffer к ArrayList<String>, который не будет работать во время выполнения.


После обновления:

Я предполагаю, что вы пытаетесь создать parallel class hierarchy, и получил перепутались в этом. Может быть, вы хотели ваш ExerciseInterface выглядеть следующим образом:

// Notice the use of `T` in `SetInterface<T>` instead of `SetInterface<?>` 
interface ExerciseInterface<T extends SetInterface<T>> { 
    SetInterface<T> getSet(int pos); 
    void addSet(SetInterface<T> set); 
} 

и тогда ваш класс WeightsExercise будет изменен так:

class WeightsExercise implements ExerciseInterface<WeightsSet> { 
    @Override 
    public SetInterface<WeightsSet> getSet(int pos) {return null;} 

    @Override 
    public void addSet(SetInterface<WeightsSet> set) {} 
} 

Вы также должны были бы сделать ваш Workout класс родовым так:

public class Workout<U extends SetInterface<U>, T extends ExerciseInterface<U>> { 

} 

Затем замените все случаи возникновения ExerciseInterface<SetInterface<?>> на ExerciseInterface<U> в вашем Workout класс.

И создать экземпляр Workout, как это:

Workout<WeightsSet, WeightsExercise> workout = new Workout<>("Wok"); 
workout.addExerciseA(weightsExercise); 

Это то, что делают правильный дизайн ИМО.


Рекомендуемый пост:

Ссылки:

+0

Cheers Rohit, я возьму это на борту. Я также читал некоторые из этих ресурсов, но я буду смотреть дальше. Я взял верхний ограниченный шаблон, хотя и теперь существует другая общая проблема. См. Редактировать 2 – mgibson

+0

Будет проверять это как можно скорее. Цените свое время – mgibson

+0

Хмм Рохит, там, кажется, есть что-то отличное. Однако то, что я пытаюсь достичь, это возможность добавлять WeightsSet и WeightsExercise к тренировке да, а также другое упражнение, которое реализует ExerciseInterace. – mgibson

Смежные вопросы