5

Java resolving default method conflicts: why using super keyword?

I'm reading the book "Core Java SE 9 for the impatient". In section "Resolving Default Method Conflicts", I found that when resolving default method conflicts, the super keyword is used. But I don't understand why use the super keyword.

From this link: https://docs.oracle.com/javase/tutorial/java/IandI/override.html I know that the super keyword is required(otherwise the program won't compile).

But it seems counterintuitive. From my understanding, interface "Identified" has no super class. Why not just use "return Identified.getId();" ?

public interface Person {
    default int getId() {
        return 0;
    }
}

public interface Identified {
    default int getId() {
        return Math.abs(hashCode());
    }
}

public class Employee implements Person, Identified {
    public int getId() {
        return Identified.super.getId();
    }
}

There are some explanations in this question and this question but none of them explained why keyword super is used.

CodingNow
  • 998
  • 1
  • 11
  • 23
  • 1
    `Identified.getId()` is static. You want to return `super.getId()` and use `Identified` to tell the compiler which of the conflicting methods to use. Think of it as `(Identified.super).getId()` – c0der Mar 03 '18 at 04:27
  • 1
    That is actually pretty confusing, come to think of it. It's inconsistent with how `T.super.x` is used otherwise, which is to view the referred-to object as an instance of the superclass of `T` (see [§15.11.2](https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.11.2)). I think it probably would have made more sense intuitively to use qualified `this` as in `Identified.this.getId()`, but that might have created more ambiguities for the designers to solve. – Radiodef Mar 03 '18 at 04:35
  • 1
    @Radiodef or IMO it would be cleaner to be able to say something like `super.Identified.getId()` in the sense that *which super*, I don't know. But either way this is a very confusing syntax – Eugene Mar 04 '18 at 18:52

3 Answers3

5

Because Identified.getId() would imply that getId is a static method. Before Java 8, this super keyword was only used to refer to a super class in the form of super.getId().

In your case, Identified.super.getId() does not mean "The getId() of the super of Identified", but rather "The getId() of the super that is from Identified".

T Tse
  • 786
  • 7
  • 19
3

It is clear that Employee has a conflict; the method signature default int getId() of both Person and Identified are identical.

JLS 9.4.1.3 describes this as a behavioral conflict which leads to an error. Naturally you must decide which getId() method should be invoked (either override it, or choose the default implementation from either Person or Identified.

JLS 9.4.1.1 (Overriding by Instance Methods) provides a clue:

An overridden default method can be accessed by using a method invocation expression (§15.12) that contains the keyword super qualified by a superinterface name.

But the most formalized reason for the use of the word super comes from JLS 15.12 and specifically 15.12.1: Compile-Time Step 1: Determine Class or Interface to Search

The section describes the 6 forms that a method invocation can take.

One form is Identified.getId() is reserved for a static reference and is discussed in another answer.

Another form is super.getId(). This is the more common use of the word super; which refers to the superclass of the class.

This leads to the final form mentioned in 15.12.1: TypeName.super.getId()

Here the word super has only one purpose. If the word super appears to the left of the method getId(), and if TypeName appears to the left of super, then (i) TypeName must be either a class or interface, (ii) If TypeName is a class it gets priority over an interface, (iii) If TypeName is not a class it must be an interface.

So this finally leads to the explanation of super in this context:

Super in this case is used to match the form TypeName.super.identifier which is the defined way (by JLS 15.12.1) to call the method identifier from interface TypeName.

Ian Mc
  • 5,656
  • 4
  • 18
  • 25
1

Because the Indentified.getId() syntax is already used for static method calls. The C++ syntax Identifier::getId() could have been nice, but Java is using it for method reference so a no-go as well. The Identified.this.getId() syntax couldn't be used either because it's already used to avec à method from an outer class when you have nested classes.

I guess at some point they just ran out of options. But I agree the syntax can be kind of misleading, but since in Java you can't call a "grandparent" method, using "super" might have been seen as a lesser evil.

Simon Berthiaume
  • 643
  • 4
  • 11