Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 Error: Interface Inherits Abstract and Default

I'm trying to write a library of collection interfaces that implement most of the methods in the standard Collection API using the new default method syntax in Java 8. Here's a small sample of what I'm going for:

public interface MyCollection<E> extends Collection<E> {
    @Override default boolean isEmpty() {
        return !iterator().hasNext();
    }
    //provide more default overrides below...
}

public interface MyList<E> extends MyCollection<E>, List<E> {
    @Override default Iterator<E>iterator(){
        return listIterator();
    }
    //provide more list-specific default overrides below...
}

However, even this simple example is met with a compiler error:

error: interface MyList<E> inherits abstract and default
       for isEmpty() from types MyCollection and List

From my understanding of default methods, this should be allowed since only one of the extended interfaces provides a default implementation, but apparently that's not the case. What's going on here? Is there a way to get this to do what I want?

like image 330
Ryan Hilbert Avatar asked Sep 24 '15 05:09

Ryan Hilbert


People also ask

Can we override default method of interface Java 8?

A default method cannot override a method from java.

Can default methods be inherited?

Default methods and abstract methods in interfaces are inherited like instance methods. However, when the supertypes of a class or interface provide multiple default methods with the same signature, the Java compiler follows inheritance rules to resolve the name conflict.

CAN interface have 2 default methods?

Multiple Defaults With default functions in interfaces, there is a possibility that a class is implementing two interfaces with same default methods. The following code explains how this ambiguity can be resolved.

Can default methods be abstract?

Abstract Classes Compared to Interfaces With interfaces, all fields are automatically public, static, and final, and all methods that you declare or define (as default methods) are public. In addition, you can extend only one class, whether or not it is abstract, whereas you can implement any number of interfaces.


1 Answers

This is explained in section 9.4.1.3 (Inheriting Methods with Override-Equivalent Signatures) of the Java Language Specification:

It is possible for an interface to inherit several methods with override-equivalent signatures (§8.4.2).

...

Similarly, when an abstract and a default method with matching signatures are inherited, we produce an error. In this case, it would be possible to give priority to one or the other - perhaps we would assume that the default method provides a reasonable implementation for the abstract method, too. But this is risky, since other than the coincidental name and signature, we have no reason to believe that the default method behaves consistently with the abstract method's contract - the default method may not have even existed when the subinterface was originally developed. It is safer in this situation to ask the user to actively assert that the default implementation is appropriate (via an overriding declaration).

So since both MyCollection and List define a method isEmpty() and one is default and the other is abstract, the compiler requires the subinterface to explicitly declare which one it should inherit by overriding the method again. If you want the default method of MyCollection to be inherited, then you can invoke it in the overriding implementation:

public interface MyList<E> extends MyCollection<E>, List<E> {
    @Override default boolean isEmpty() {
        return MyCollection.super.isEmpty();
    }

    @Override default Iterator<E> iterator(){
        return listIterator();
    }
    ...
}

If you want MyList to keep the isEmpty() abstract (which I don't think you want), you can do:

public interface MyList<E> extends MyCollection<E>, List<E> {
    @Override boolean isEmpty();

    @Override default Iterator<E> iterator(){
        return listIterator();
    }
    ...
}
like image 146
M A Avatar answered Sep 28 '22 01:09

M A