Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Default methods and interfaces extending other interfaces

Suppose there are two interfaces Interface1 and Interface2 where Interface2 extends Interface1.

interface Interface1 {      default void method() {         System.out.println("1");     }      // Other methods }  interface Interface2 extends Interface1 {      @Override     default void method() {         System.out.println("2");     }      // Other methods } 

Suppose I want to create a class that implements Interface2 but I want method() to be the version in Interface1. If I write

class MyClass implements Interface1, Interface2 {      public void method() {         Interface1.super.method();     } } 

I get the compilation error:

bad type qualifier in default super call: redundant interface Interface1 is extended by Interface2

It is possible to get around this by creating a third interface:

interface Interface3 extends Interface1 {      default void method() {         Interface1.super.method();     } } 

Then:

class MyClass implements Interface1, Interface2, Interface3 {      public void method() {         Interface3.super.method();     } } 

This compiles fine, and if I instantiate a new MyClass and invoke method(), the output is 1 as expected.

So my question is, given that it is so easy to get around the restriction that you can only write InterfaceName.super.method() for the most specific interface in a chain, what is the reason for the restriction? What problems are prevented by disallowing you from writing Interface1.super.method() in the first place?

like image 620
Paul Boddington Avatar asked Apr 08 '15 21:04

Paul Boddington


People also ask

Do interfaces extend other interfaces?

An interface can extend other interfaces, just as a class subclass or extend another class. However, whereas a class can extend only one other class, an interface can extend any number of interfaces.

What are default methods in interface?

Default methods enable you to add new functionality to existing interfaces and ensure binary compatibility with code written for older versions of those interfaces. In particular, default methods enable you to add methods that accept lambda expressions as parameters to existing interfaces.

Can Java interfaces extend other interfaces?

Answer is: Yes. An interface may be declared to be a direct extension of one or more other interfaces, meaning that it implicitly specifies all the member types, abstract methods, and constants of the interfaces it extends, except for any member types and constants that it may hide.


1 Answers

This is exactly addressed by the JLS in 15.12.3. "Compile-Time Step 3: Is the Chosen Method Appropriate?".

If the form is TypeName . super . [TypeArguments] Identifier, then:

  • […]
  • If TypeName denotes an interface, let T be the type declaration immediately enclosing the method invocation. A compile-time error occurs if there exists a method, distinct from the compile-time declaration, that overrides (§9.4.1) the compile-time declaration from a direct superclass or direct superinterface of T.

The JLS goes on to explain why the rule is in place:

In the case that a superinterface overrides a method declared in a grandparent interface, this rule prevents the child interface from "skipping" the override by simply adding the grandparent to its list of direct superinterfaces. The appropriate way to access functionality of a grandparent is through the direct superinterface, and only if that interface chooses to expose the desired behavior.

So it more or less exists specifically to stop you from doing what you're trying to do.

But the JLS also seems to acknowledge your workaround:

(Alternately, the developer is free to define his own additional superinterface that exposes the desired behavior with a super method invocation.)

like image 151
Radiodef Avatar answered Sep 23 '22 10:09

Radiodef