1

I am trying to understand how default methods deal with diamond problem in various scenarios.
And, this is one of the scenario which I'm not able to understand.

Following is the description,
1. Interface with a default method method()
2. Abstract Class with a method method()
3. Concrete Class implementing the above interface and extending the abstract class.

interface Interface {
    default void method() {
        System.out.println("Interface method");
    }
}


abstract class AbstractClass {
    void method() {
            System.out.println("Abstract class method");
    }
}


// Concrete class definition first starts
public class ConcreteClass extends AbstractClass implements Interface {

    @Override
    public void method() {
        super.method();
    }

    public static void main(String[] args) {
        Interface test = new ConcreteClass();
        test.method();
    }
}
// Concrete class definition first ends

// Concrete class definition Second starts
public class ConcreteClass extends AbstractClass implements Interface {

    public static void main(String[] args) {
        Interface test = new ConcreteClass();
        test.method();
    }
}
// Concrete class definition Second ends

My queries,

1. Why does definition first always gives output as "Abstract class method" even when I use the Interface type for concrete class object?
2. Why definition second doesn't compile?
If compiler is using abstract class implementation in definition first, then it should be able to identify that it will always use Abstract class implementation in definition second.

This behavior is very confusing to me and any help is greatly appreciated. Otherwise, the more I delve deeper into this, the more confusing it gets.


Edit 1 :
Compilation error in second definition is "The inherited method AbstractClass.method() cannot hide the public abstract method in Interface"

dSanders
  • 165
  • 11
  • (1) "even when I cast the concrete class object to interface" what do you mean by *cast*? (2) what compilation error are you getting (it should contain answer to *why* part)? – Pshemo Sep 23 '19 at 16:00
  • Added the compilation error. – dSanders Sep 23 '19 at 16:06
  • Possible duplicate of [Purpose of Default or Defender methods in Java 8](https://stackoverflow.com/questions/19998309/purpose-of-default-or-defender-methods-in-java-8) – Naman Sep 23 '19 at 16:34

1 Answers1

3

Default methods are just that: defaults. If there is an implementation, it will be used. If there isn't, the default will be used. There is no diamond problem here (there can be with multiple defaults, however).

1) Dynamic dispatch

2) The abstract class gives the method named method package-private access; the interface demands it be public.

Michael
  • 41,989
  • 11
  • 82
  • 128
  • @dSanders Specifically regarding (1), AbstractClass specifies an implementation for method() that overrides the default Interface::method. Any subclass of abstract class will call AbstractClass::method unless said subclass overrides it by defining Subclass::method in turn. – Avi Sep 23 '19 at 16:09
  • Okay, so default methods are used as a last resort for method definition. "The abstract class gives the method named method package-private access; the interface demands it be public." I did not get this. – dSanders Sep 23 '19 at 16:13
  • 1
    If you have an interface, the method is implicitly public, whether you add the `public` keyword or not. The method in your abstract class is not public. It is defined at the default access level (package private). The issue is that package private is more restrictive than public. – Michael Sep 23 '19 at 16:15
  • Oh, I got it. So the compilation error is coming because the Abstract class is making the method more restrictive and, if I make its method as public, there will be no compilation error. – dSanders Sep 23 '19 at 16:48
  • Thank you for the clarification. – dSanders Sep 23 '19 at 16:50