Forced SingleTask
constructors, which also implement all List
methods, are not very elegant, and the default methods are not intended to define objects that are similar to the type your SingleTask
interface looks like.
There are several reasons why default method methods are a bad idea, the most obvious of which is that any developer can simply override your default method, destroying your trait.
And this is exactly what is happening here: since AbstractList
explicitly declares get()
and size()
as abstract
, this means that SingleTask
inherits them, and not the standard implementations that you might have had in the superinterface.
JLS 8.4.8 :
Class C inherits from its direct superclass and direct superinterfaces of all abstract and default (ยง 9.4) methods m, for which everything is true:
...
- No particular method that C inherits from its direct superclass has a signature, which is a subset of signature m.
Given all this, the simplest solution is probably this:
public abstract class SingleTask extends AbstractList<Runnable> implements Runnable { @Override public final Runnable get(final int x) { if (x != 0) { throw new IndexOutOfBoundsException(); } return this; } @Override public final int size() { return 1; } @Override public abstract void run(); }
Its disadvantage is that your tasks must expand on SingleTask
and therefore cannot distribute anything else on the plus side, although they do not need to deal with the fact that the task is also a List
, they only need to implement run()
.
In the long run, although I would prefer composition over inheritance, tasks simply return a list of runnables rather than themselves.
source share