86

A new feature coming in JDK 8 allows you to add to an existing interface while preserving binary compatibility.

The syntax is like

public interface SomeInterface() {
  void existingInterface();
  void newInterface() default SomeClass.defaultImplementation;
}

This way for all existing implementations of SomeInterface when they upgrade to this new version they don't all suddenly have compiles errors around newInterface().

While this is neat, what happens when you are implementing two interfaces which both have added a new defaulted method which you did not implement? Let me explain with an example.

public interface Attendance {
   boolean present() default DefaultAttendance.present;
}

public interface Timeline {
   boolean present() default DefaultTimeline.present;
}

public class TimeTravelingStudent implements Attendance, Timeline {

}

// which code gets called?
new TimeTravelingStudent().present();

Has this been defined as part of JDK 8 yet?

I found the Java gods talking about something similar here http://cs.oswego.edu/pipermail/lambda-lib/2011-February/000068.html, but its part of private mailing list and I cannot ask them directly.

See this for more details on how defaults are going to be used in JDK 8 and extending the Collection interface to support lambdas: https://oracleus.wingateweb.com/published/oracleus2011/sessions/25066/25066_Cho223662.pdf

Jacob G.
  • 28,856
  • 5
  • 62
  • 116
Pyrolistical
  • 27,624
  • 21
  • 81
  • 106
  • Another useful material for this is http://cr.openjdk.java.net/~briangoetz/lambda/Defender%20Methods%20v4.pdf – MohamedSanaulla Jun 24 '12 at 14:39
  • Sidenote: the final syntax for default implementations of interface methods turned out to be different (code block instead of a reference to an external class). – Joachim Sauer May 27 '13 at 15:47
  • 4
    Java has always had multiple inheritance of *types*. Default methods add multiple inheritance of *behavior*, but not of *state*. (Multiple inheritance of state in languages like C++ is where most of the trouble comes from.) – Brian Goetz Jun 21 '14 at 02:05
  • The video session to watch is here http://medianetwork.oracle.com/video/player/1113272518001 This is the designer talking about the feature called Virtual Extensions. He also talks about how this doesn't break backward compatibility. – Peter Lawrey Oct 22 '11 at 07:35
  • So the answer to my example is currently you get a compiler error. But they are open to other solutions. – Pyrolistical Oct 22 '11 at 08:15
  • @Pyrolistical could you please explain what `open to other solutions` means? – ajay Feb 26 '15 at 09:41
  • @ajay I forget, but its kind of moot now that Java 8 is out now. You can run that code and see for yourself what actually happens. – Pyrolistical Feb 28 '15 at 01:18

8 Answers8

67

The answer to the duplicate operation is:

To solve multiple inheritance issue a class implementing two interfaces providing a default implementation for the same method name and signature must provide an implementation of the method. [Full Article]

My answer to your question is: Yes, it is a form of multiple inheritance, because you can inherit behavior from different parents. What's missing is to inherit states, i. e., attributes.

H-Man2
  • 3,169
  • 20
  • 19
  • 2
    +1: When there is a conflict it will take a more specific implementation over a less specific one, allowing you to specify which one it should be if there is a conflict. – Peter Lawrey Oct 22 '11 at 06:53
  • @H-Man2 I don't get it. If that is true it means it would break binary compatibility. Now maybe that isn't so bad as breaking binary compatibility to prevent multiple inheritance, breaking binary compatibility sucks. – Pyrolistical Oct 22 '11 at 07:21
  • @PeterLawrey which one is more specific in my example? – Pyrolistical Oct 22 '11 at 07:22
  • @Pyrolistical: No, it does not break compatibility, because the compiler can translate the default implementation to a normal method call. I think it is more a macro then real inheritance, but can simulate aspects of mul.-inheritance. Maybe the video from Peter provides a more detailed answer. – H-Man2 Oct 22 '11 at 07:43
  • actually we can get around the missing states by having abstract getters and setters, the implementing class can add the states ... – vikkyhacks Mar 08 '18 at 18:13
9

I know this is a old post, but as i'm working with this stuff...

You will have an error from the compiler, telling you that:

 class TimeTravelingStudent inherits unrelated defaults for present() from types Attendance and Timeline reference to present is ambiguous, both method present() in Timeline and method present() in Attendance match.

Enkk
  • 376
  • 3
  • 6
9

There are two scenarios:

1) First, that was mentioned, where there is no most specific interface

public interface A {
   default void doStuff(){ /* implementation */ }
}

public interface B {
   default void doStuff() { /* implementation */ } 
}

public class C implements A, B {
// option 1: own implementation
// OR
// option 2: use new syntax to call specific interface or face compilation error
  void doStuff(){
      B.super.doStuff();
  }
}

2) Second, when there IS a more specific interface:

   public interface A {
       default void doStuff() { /* implementation */ } 
    }

    public interface B extends A {
       default void doStuff() { /* implementation */ } 
    }

    public class C implements A, B {
    // will use method from B, as it is "closer" to C
    }
Andrejs
  • 10,803
  • 4
  • 43
  • 48
5

In short: it's a compile time error, must override the method by hand in the implementation.


Purpose of default method

The major purpose to introduce default method in Java 8, is to make interface extendable, without breaking existing implementations (there are so many 3rd party Java libraries).

And multiple inheritance like in C++ is actually intended to be avoided, that's definitely not the purpose of default method in Java.


How to override

2 options:

  • Override the method, with its own logic.
  • Override the method, call one of the interface's method via super, format: <interface_name>.super.<method_name>();

Tips:

  • method from interface is default to public, so don't forget to add public keyword when override it.
Eric
  • 22,183
  • 20
  • 145
  • 196
4

My answer to your question is: Yes, it is a form of multiple inheritance, because you can inherit behavior from different parents. What's missing is to inherit states, i. e., attributes.

Yes, but you can add getters and setters to your interface that the implementing classes then must implement. Nevertheless, the implementing classes don't inherit attributes. So, AFAICS, it's more like a trait-style solution rather than a multiple inheritance style solution.

OlliP
  • 1,545
  • 11
  • 22
3

If anyone's still looking for an answer, in case a class implements two interfaces with the same default method then the class needs to resolve the disambiguity by providing an implementation of its own. Look at this tutorial for more details on how inheritance in default methods work.

0

"How will we distinguish the methods" was a question that was put on Stackoverflow and referred to this question concrete methods in interfaces Java1.8

The following is an example that should answer that question:

interface A{
default public void m(){
System.out.println("Interface A: m()");
}
}

interface B{
default public void m(){
System.out.println("Interface B: m()");
}
}

 class C implements A,B { 

 public void m(){
  System.out.println("Concrete C: m()");   
 }

public static void main(String[] args) {
   C aC = new C();
   aC.m();
   new A(){}.m();
   new B(){}.m();
}
}

Class C above must implement its own concrete method of the interfaces A and B. Namely:

 public void m(){
  System.out.println("Interface C: m()");   
 }

To call a concrete implementation of a method from a specific interface, you can instantiate the interface and explicitly call the concrete method of that interface

For example, the following code calls the concrete implementation of the method m() from interface A:

new A(){}.m();

The output of the above would be:

Interface A: m()

-1

As far as I see it, it is no multiple inheritance because they are stateless. So virtual extension methods don't support full object or class functionality.

Peter
  • 1,769
  • 1
  • 14
  • 18