35

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.

Community
  • 1
  • 1
Rogue
  • 11,105
  • 5
  • 45
  • 71
  • 3
    what would be the meaning of a private method in an interface? – njzk2 Dec 08 '14 at 22:48
  • @njzk2 per the question "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". This is an interface for an enum, so while it's a little complexly put together, I wouldn't say there's a lot of better ways for what I'm doing outside of this question. – Rogue Dec 08 '14 at 22:49
  • a private method can only be called from its own class. In the case of an interface, it would mean a method that cannot be called. – njzk2 Dec 08 '14 at 22:51
  • when you define an interface, you usually are going to use it. elevating the visibility in the implementation is not going to do anything. – njzk2 Dec 08 '14 at 22:51
  • 4
    I don't think there's going to be anything but an "opinion-based answer" available. – Louis Wasserman Dec 08 '14 at 22:52
  • oh my apologies @njzk2, I guess I took your question a different way. I can't think of a use for `private` off the top of my head other than access within other default interface methods themselves. `protected` would still be relevant here, however. – Rogue Dec 08 '14 at 22:52
  • 1
    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 Dec 08 '14 at 22:53
  • In some sense, for an **abstract** class, a non-abstract method or a member actually exists in that class. So when you call `super.method()` you're actually calling a real thing. But a default method of an interface isn't something that actually exists, just a default that is used if you don't override it. – ajb Dec 08 '14 at 22:53
  • @ajb, but you can call the method directly via `Testerface.super.example()` from a subclass? (as seen in my example) – Rogue Dec 08 '14 at 22:54
  • Hmmm... I didn't realize you could do this. I thought this was illegal code. My mistake. – ajb Dec 08 '14 at 22:57
  • Per @njzk2 `private` wouldn't make sense. `protected` wouldn't either, since only subclasses can override protected methods. Concrete classes wouldn't extend an interface - they'd implement it. If you could make a default interface method `protected` it would be essentially the same as making it final. – pmorken Dec 08 '14 at 23:37
  • 8
    @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 Dec 09 '14 at 00:56
  • @BrianGoetz: but that would be entirely useless. An interface defines what methods a class implements, it is not its place to include concrete implementation (unless very simple ones, as in the case of the `default`). If you need to call a private method in your `default`, then there is something smelly in your design. (also you couldn't make a static method either in an interface in java 7) – njzk2 Dec 09 '14 at 14:07
  • As a side note, do we realize that this is essentially multiple inheritance? What happens if I have 2 interfaces defining the same method, with a different default? – njzk2 Dec 09 '14 at 14:09
  • 1
    @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 Dec 09 '14 at 17:11

1 Answers1

51

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.

Brian Goetz
  • 90,105
  • 23
  • 150
  • 161
  • Doesn't the lack of private methods on interfaces combined with default methods encourage developers to expose mutators? – Jeff Jan 06 '15 at 14:50
  • 1
    I think "encourage" is the wrong word. It fails to discourage. We would have loved to get private methods into interfaces in 8, but there's a limit to how much you can do in the time/resources you have. – Brian Goetz Jan 06 '15 at 16:15
  • 22
    Good news: private methods in interfaces look like they will make Java 9. – Brian Goetz Feb 18 '15 at 16:31
  • @BrianGoetz I'm lucky I stumbled across an old question of mine, thanks for the update! – Rogue Feb 19 '15 at 05:57
  • 1
    Well, despite all these new features in Java 8/9 seem pretty useful and convenient I think it is getting a little confusing. To my own sense of 'interface' its definition is closer to 'contract' rather than what it has become. I think it will be much more beautiful to add a new entity in the language which represents 'a class without a state' rather than augmenting the 'interface' one. What I think of is something like 'mixin'. – egelev Dec 28 '16 at 07:02
  • 1
    @egelev As no one should find surprising, this was extensively debated before this decision was taken. The conclusion was that creating a new top-level abstraction (mixin, trait, whatever) that was almost but not exactly the same as interfaces, would be even more confusing and intrusive -- and probably would have also failed to live up to people's pre-existing expectations of what mixin/trait meant. (It's easy to say "this is imperfect, you should have done something else", but one also must think more deeply about whether the alternatives might themselves actually have been worse.) – Brian Goetz Dec 28 '16 at 14:53
  • @egelev That's actually a very good point. I found myself starting to use default methods, until a certain point where I made the exact observation you made. I couldn't agree more. – ShellFish May 10 '17 at 05:13