I have an Interface Worker
like below:
public interface Worker<T> {
public void doAllTasks (List<? extends T> tasks);
}
There is an Abstract Class that uses above interface,
public abstract class AbstractWorker<T> implements Worker<T> {
...
public abstract void doAllTasks (List<? extends T> tasks);
...
}
And there is a concrete Worker extending from this Abstract class,
public class ConcreteWorker<T extends Task> extends AbstractWorker<T> {
@Override
public void doAllTasks(List<? extends T> tasks) {
....
}
}
Notice the Task
in the above class definition? That is an interface. SpecialTask
is a concrete class that implements Task
interface. Now once this structure is there, I wish to use this classes in my main Application like below:
Class Application {
public AbstractWorker<? extends Task> myWorker;
main() {
....
List<SpecialTask> listOfTasks = new ArrayList<SpecialTask>();
myWorker = new ConcreteWorker<SpecialTask>();
myWorker.doAllTasks (listOfTasks); <-------------- ERROR!!!
}
}
IDE shows me the following error in the above marked line:
The method doAllTasks(List<? extends capture#3-of extends Task>) in the type
AbstractWorker<capture#3-of extends Task> is not applicable for the
arguments (List<SpecialTask>)
What I am trying to do is - in my main Application I want to first declare the Abstract version of my Worker first and later, based on some logic I want to instantiate a concrete version of that worker. I do not know before hand which particular implementation of Task
I will need (so it could be the SpecialTask
or AnotherSpecialTask
etc. - assuming both of them implements Task
)
Honestly being new to Java, I could not make any head or tail of that error message. Can someone please show me where am I going wrong?
The problem is that the type of myWorker
is just AbstractWorker<? extends Task>
- in other words, it doesn't know that the type argument is really SpecialTask
. It could be an AbstractWorker<SomeOtherTask>
, which wouldn't know what to do with a List<SpecialTask>
.
If you only ever want myWorker
to hold a worker that can deal with SpecialTask
, you can just use:
public AbstractWorker<SpecialTask> myWorker;
That's still not depending on ConcreteWorker
, but it is saying that it's definitely not just an AbstractWorker<SomeOtherTask>
for example.
See more on this question at Stackoverflow