32

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?

Radiodef
  • 37,180
  • 14
  • 90
  • 125
Paul Boddington
  • 37,127
  • 10
  • 65
  • 116
  • 3
    If `Interface2 extends Interface1`, in which scenario you want a class to implement them *both*? – Maroun Apr 08 '15 at 21:58
  • @MarounMaroun You're right, there's no point writing them both. It's just that on IntelliJ I got a less helpful error message if I only wrote `Interface2`. – Paul Boddington Apr 08 '15 at 22:00
  • methods in `interfaces` have a body, guess I have to revise my basics. I thought they are suppose to be abstract – Shrikant Havale Apr 08 '15 at 22:00
  • 2
    @ShrikantHavale It's new to Java 8. I almost wish they hadn't allowed it as it's opened up a whole can of worms. – Paul Boddington Apr 08 '15 at 22:02
  • 2
    @pbabcdefp there is no can of worms if you use it properly (this vague statement applies to many other concepts)... – assylias Apr 08 '15 at 22:05
  • @assylias the whole point of interfaces is abstraction , what is the point of having implementation of methods in interfaces? its messing up the design for backward compatibility – Stunner Nov 26 '20 at 04:22

1 Answers1

18

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.)

Community
  • 1
  • 1
Radiodef
  • 37,180
  • 14
  • 90
  • 125
  • That's really interesting. They're ok with the workaraound (which seems like a hack to me), but the only reason they've disallowed the original is that they don't consider it "appropriate". – Paul Boddington Apr 08 '15 at 22:12
  • 1
    Yes, I find that strange as well. I would understand if, for example, the javadoc automatically detected which implementation the subclass chooses to use and generated the appropriate documentation. But I doubt it's the case, since, AFAIK, javadoc doesn't care about the body of methods. – JB Nizet Apr 08 '15 at 22:23
  • 2
    I think "they're OK with it" is a misread of this comment (mostly, hearing what you want to hear). In general, the rules are there for good reasons (and the reason is even given here); when the compiler says "don't do that", your first thought should not be "let me remove the blade guard and show the nanny state who is most clever." In this case, it was not possible to prevent users from doing dumb things in all situations, but still not recommended, and that doesn't mean we should give up on warning the user when we can. – Brian Goetz Apr 09 '15 at 07:39
  • @BrianGoetz Thanks for your comment. To be clear, I agree about the nanny state. What struck me personally was that the prose was there at all. (And if the rule was important enough to warrant the side-note, why immediately point out how to defeat it?) In most cases, only the algorithm is described. – Radiodef Apr 09 '15 at 08:04
  • 2
    @Radiodef Fair comments. The reality is: multiple inheritance is more complicated than single inheritance, even after dodging 90% of the complexity by outlawing multiple inheritance of state and choosing clever conflict-resolution rules. Users have 20 years experience of "this is what inheritance/overriding means" conditioned by single inheritance, and their intuition often fails them when they try to apply it to multiple inheritance. We can make it easier by outlawing the truly problematic bits, but "easier" and "easy" are not the same. – Brian Goetz Apr 09 '15 at 08:18
  • 2
    @BrianGoetz I see. So whether it's useful or not, we have the opportunity to shoot ourselves in the foot with a feature outside of our familiar notions ("spaghetti types"), and it's difficult to outlaw the possibility. (And after thinking about it, it seems that conflict solutions that don't allow the override circumvention trick tend to be more rigid than useful.) Thanks again for your time. – Radiodef Apr 09 '15 at 09:42