1

我的目标很简单。我有一个SetInterface<T>

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

到目前为止,一切都很好。

问题出现在我尝试创建一个包含不同类的通用集合,这些类都实现了练习接口。

我对泛型相当陌生,我一直认为我已经解决了一些问题,但我所做的只是推动错误。

这个问题几乎可以用我的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<?>>)

重申一下,我有一个不同类型的 Set 实现的 SetInterface。

我也有不同的练习,这些练习反映了 Sets。例如:

BodyWeightExercise implements <SetInterface<BodyweightSet>>

WeightsExercise implements <SetInterface<WeightsSet>>

所以我的目标是拥有一个不同练习的集合和一种允许我添加到该集合中的方法。

任何帮助将不胜感激,我已经为此失去了几根头发。

干杯。

编辑:如果这不可行,任何指向更可行方向的指针都将不胜感激。

EDIT2:我将 List 更改为,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);}

}

4

1 回答 1

2

您应该将列表声明更改为:

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

null当您使用上限通配符(我认为您在这里并不真正需要)时,除了, 和以前从中获取的元素之外,您无法向列表添加任何内容。

那是因为,您并不确切知道它实际引用的具体参数化列表类型。例如:List<? extends CharSequence>可以引用 aArrayList<String>ArrayList<StringBuffer>. 因此,您不能在该列表中添加任何内容,因为它不是类型安全的。您可能正在向 中添加一个StringBuffer对象ArrayList<String>,这将在运行时失败。


更新后:

我猜你正在尝试创建一个并行的类层次结构,并且搞砸了。也许,你希望你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);

这将是一个正确的设计 IMO。


推荐帖子:

参考:

于 2013-08-28T18:10:42.443 回答