34
votes

Let's take an example:

public interface Testerface {

    default public String example() {
        return "Hello";
    }

}

public class Tester implements Testerface {

    @Override
    public String example() {
        return Testerface.super.example() + " world!";
    }


}

public class Internet {

    public static void main(String[] args) {
        System.out.println(new Tester().example());
    }

}

Simply enough, this would print Hello world!. But say I was doing something else with the return value of Testerface#example, for instance initializing a data file and returning a sensitive internal value that shouldn't leave the implementing class. Why does Java not allow access modifiers on default interface methods? Why can't they be protected/private and potentially elevated by a subclass (similar in how a class that extends a parent class can use a more visible modifier for an overridden method)?

A common solution is moving to an abstract class however in my specific case, I have an interface for enums, so that does not apply here. I imagine it was either overlooked or because the original idea behind interfaces that they are a "contract" of available methods, but I suppose I want input as to what's going on with this.

I've read "Why is “final” not allowed in Java 8 interface methods?", which states:

The basic idea of a default method is: it is an interface method with a default implementation, and a derived class can provide a more specific implementation

And it sounds to me like visibility wouldn't break that aspect at all.

As with the linked question since it looks like it had trouble being closed, an authoritative answer would be appreciated in this matter, rather than opinion-based ones.

1
what would be the meaning of a private method in an interface?njzk2
I don't think there's going to be anything but an "opinion-based answer" available.Louis Wasserman
Create a private class with protected static methods for the stuff your default method wants to use but not leak out into the world. That said, that sounds like bad design.Havvy
@njzk2 (and pmorken): You seem to be suffering a failure of imagination. A private method in an interface could be called from other method bodies (static or default) in the interface, and is useful in exactly the same ways as private methods in classes are.Brian Goetz
@njzk2 I think you're a few years late to the party :) All of these issues were gone over in excruciating detail several years ago by the JSR-335 EG. Short answer: Java always had multiple inheritance -- of types. Default methods adds multiple inheritance of behavior. What we still do not have is multiple inheritance of state, which is where most nasty problems come from (like diamonds.) Now you need to go update your model of how the language works...Brian Goetz

1 Answers

48
votes

As we saw in What is the reason why “synchronized” is not allowed in Java 8 interface methods? and Why is "final" not allowed in Java 8 interface methods?, extending interfaces to define behavior is more subtle than it might first appear. It turns out that each of the possible modifiers has their own story; its not simply a matter of blindly copying from how classes work. (This is at least obvious in hindsight, as tools for OO modeling that work for single inheritance do not automatically work for multiple inheritance.)

Let's start with the obvious answer: interfaces have always been restricted to only having public members, and while we added default methods and static methods to interfaces in Java 8, that doesn't mean we have to change everything just to be "more like" classes.

Unlike with synchronized and final, which would have been serious mistakes to support for default methods, weaker accessibilities, especially private, are reasonable features to consider. Private interface methods, whether static or instance (note that these would not be defaults, since they do not participate in inheritance) are a perfectly sensible tool (though they can be easily simulated by nonpublic helper classes.)

We actually did consider doing private interface methods in Java 8; this was mostly something that just fell off the bottom of the list due to resource and time constraints. It is quite possible this feature might reappear on the to-do list some day. (UPDATE: private methods in interfaces were added in Java 9.)

Package and protected methods, however, are more complicated than they look; the complexity of multiple inheritance and the complexity of the true meaning of protected would interact in all sorts of no-so-fun ways. So I wouldn't hold your breath for that.

So, the short answer is, private interface methods is something we could have done in 8, but we couldn't do everything that could have been done and still ship, so it was cut, but could come back.