在子类中定义列表类型的实现方案咨询
解决Workout子类返回特定Exercise子类型列表的问题
这个问题我之前也碰到过,核心原因是Java泛型的不变性——哪怕ExerciseCircuit是Exercise的子类,ArrayList<ExerciseCircuit>也不能被当作ArrayList<Exercise>来用,这就导致你没法直接在子类里重写getExercises()返回更具体的列表类型。下面是最直接的解决方案:
1. 将抽象父类Workout改造为泛型类
把Workout改成带泛型参数的抽象类,让它绑定到具体的Exercise子类型,这样子类就能指定自己要操作的Exercise子类了:
import java.util.ArrayList; // 泛型参数E限定为Exercise的子类 public abstract class Workout<E extends Exercise> { private ArrayList<E> exercises; // getter和setter的类型都换成泛型E public ArrayList<E> getExercises() { return exercises; } public void setExercises(ArrayList<E> exercises) { this.exercises = exercises; } }
2. 让子类继承时指定具体的泛型类型
修改WorkoutCircuit和WorkoutSNR,继承时明确指定对应的Exercise子类型:
WorkoutCircuit类
// 指定泛型参数为ExerciseCircuit public class WorkoutCircuit extends Workout<ExerciseCircuit> { // 不需要额外重写getExercises()!父类的方法已经自动返回ArrayList<ExerciseCircuit>了 // 如果需要添加自定义逻辑,直接重写即可,返回类型会自动匹配 }
WorkoutSNR类
// 指定泛型参数为ExerciseSNR public class WorkoutSNR extends Workout<ExerciseSNR> {}
3. 使用示例
现在你可以直接调用子类的getExercises()获取对应类型的列表,完全不需要转换:
public class Main { public static void main(String[] args) { WorkoutCircuit circuitWorkout = new WorkoutCircuit(); ArrayList<ExerciseCircuit> circuitExercises = circuitWorkout.getExercises(); // 编译通过,类型完全匹配 WorkoutSNR snrWorkout = new WorkoutSNR(); ArrayList<ExerciseSNR> snrExercises = snrWorkout.getExercises(); // 同样正常工作 } }
为什么原来的方案不行?
再啰嗦两句:Java泛型是不变的,也就是说ArrayList<Sub>不是ArrayList<Super>的子类型,哪怕Sub继承自Super。这是为了类型安全——如果允许把ArrayList<ExerciseCircuit>当成ArrayList<Exercise>,那你可能会不小心往里面加一个ExerciseSNR对象,导致后续取出时出现类型转换异常。通过泛型类绑定具体类型,既保证了类型安全,又满足了子类返回特定类型列表的需求。
内容的提问来源于stack exchange,提问作者Jonas
相关产品推荐
相关产品推荐

