Search code examples
javaabstract-class

Using a List<Child class> in a method parameter requiring List<Parent class>


I have an abstract class call Task that is inherited by Task1

public abstract class Task<STATUS extends Enum> {
  STATUS getStatus();
  void setStatus(STATUS status);
}

public class Task1 extends Task<TaskStatusEnum> {
  private TaskStatusEnum status;

  public Task1() {}

  public TaskStatusEnum getStatus() { return status; }
  public void setStatus(TaskStatusEnum status) { this.status = status; }
}

// Task2, Task3, Task4, ...

public enum TaskStatusEnum {
  PLANNED, STARTED, FINISH, FAILED;
}

I'm trying to create a class who's goal is to update the tasks status

public class StateMachine {
  public StateMachine() {}

  public void startMultipleTasks(List<Task> tasks) {
    tasks.stream().forEach(task -> task.setStatus(TaskStatusEnum.STARTED));
  }
}

Why does this not compile :

Task1 myTask = new Task1();
StateMachine stateMachine = new StateMachine();

List<Task1> allTasks = List.of(myTask);

stateMachine.startMultipleTasks(allTasks); // Compilation error ; Required type: List<Task> Provided: List<Task1>

But this does :

Task1 myTask = new Task1();
StateMachine stateMachine = new StateMachine();

stateMachine.startMultipleTasks(List.of(myTask));

I know that I could store the variable allTasks in a List<Task>, but I need a List<Task1> later on in my code.

NOTE : I'm using Java 17


Solution

  • Generics are invariant, so List<Task1> is not considered a subtype of List<Task> although Task1 extends Task. You could instead use a bounded wildcard for the parameter.

    public void startMultipleTasks(List<? extends Task> tasks)