Question

Consider the following code, which is an extraction of a real use case where LinkedList<E> implements both List<E> and Deque<E>.

One can observe that both interfaces have a size() and an isEmpty() method, where the isEmpty() method could be made default in terms of size().

So, let's do that (with dummy interfaces), since Java 8 does not do it yet:

interface List<E> {
    public int size();

    default public boolean isEmpty() {
        return (size() == 0);
    }

    //more list operations
}

interface Deque<E> {
    public int size();

    default public boolean isEmpty() {
        return (size() == 0);
    }

    //more deque operations
}

class LinkedList<E> implements List<E>, Deque<E> {
    private int size;

    @Override
    public int size() {
        return size;
    }
}

Oops! We get a compile-time error on LinkedList, as it does not know which isEmpty() implementation to use, so we add this:

@Override
public boolean isEmpty() {
    return List.super.isEmpty();
}

Now we have lost practically all benefits of default methods for this use case, as it still takes us as much code to write the isEmpty() method as it did before.

But can it be solved? Yes!

Consider the following implementation:

interface Sizable {
    public int size();

    default public boolean isEmpty() {
        return (size() == 0);
    }
}

interface List<E> extends Sizable {
    //list operations
}

interface Deque<E> extends Sizable {
    //deque operations
}

class LinkedList<E> implements List<E>, Deque<E> {
    private int size;

    @Override
    public int size() {
        return size;
    }
}

So the question:

  • Is this how we, and also the JDK, are supposed to handle it in future implementations?
Was it helpful?

Solution

I strongly discourage from adding super-interfaces for unrelated interfaces just for defining default methods. Normally, you don’t have that problem as either, the interfaces are related like in your example so that a natural super-interface like Collection exists or could be defined for more than just providing default methods. Or they are really unrelated and a class implementing both is either unlikely or will have to define which semantics to inherit, anyway.

In case of the Collection API having no default method for isEmpty is intentional as size can be an expensive operation for some Collections. If your Collection shares behavior with typical Collections you may inherit from AbstractCollection.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top