21

I am just learning Java, so it is hard for me to access the possible alternatives, and the impact of such a design decision.

Java 8 adds the default methods feature to interfaces, which allows interfaces to have an implementation. This allows to extend the existing interfaces with new methods, without breaking the clients, evolving the interface over time in a backward-compatible way. However, given default implementation, such extensions are somewhat limited, and are likely to be implemented using existing interface methods of the interface or library methods. So my question is

  • Why was this language feature introduced?
  • What key new features does it support? (for instance Splititerators)
  • What other alternatives were there to support those language features? For example, why not create a new interface SplitIterable that extends Iterable?
  • What would be the impact of implementing those alternatives (poliferation of interfaces?)
  • Should I provide a default implementation for a method in the first edition of interface when it is possible to implement it as a composition of other methods?
gajos
  • 897
  • 2
  • 10
  • 21
ironstone13
  • 3,325
  • 18
  • 24
  • 4
    Nicely put question. Personally I hate the idea and think an interface should be exactly that; i.e. no implementation at all. – Bathsheba Mar 31 '16 at 14:12
  • 3
    It was added so that they could introduce the [streaming API](https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html)-related methods to collections, without breaking custom implementations of collection interfaces. – Jiri Tousek Mar 31 '16 at 14:14
  • 2
    See also Brian Goetz's paper ["Interface evolution via “public defender” methods"](http://cr.openjdk.java.net/~briangoetz/lambda/Defender%20Methods%20v3.pdf), and a related stackoverflow question ["Do Java 8 default methods break source compatibility?"](http://stackoverflow.com/questions/31188231). – Andy Thomas Mar 31 '16 at 14:29
  • 1
    Now interface is closer to abstract class but with ability to extend multiple interfaces. I think that could be the reason also. – Tomasz Mularczyk Mar 31 '16 at 14:29
  • 6
    @JiriTousek Not quite right. It was added to address the general problem of _interface evolution_; that over a long period of time, if interfaces cannot evolve, they risk losing relevance. Streams might have been the proximate cause, but the real issue is that `Collection` and friends are bordering on 20 years old, and showing their age. – Brian Goetz Mar 31 '16 at 15:00
  • 1
    Not to forget: http://stackoverflow.com/a/19998622/2711488 – Holger Mar 31 '16 at 15:07
  • It also works a lot like Scala trait and that's really cool – Paweł Prażak Apr 03 '16 at 21:09

1 Answers1

13

Why was this language feature introduced?

It was added primarily to let you add methods to existing interfaces that are already in use without breaking everyone's code, but also to share method implementations "horizontally" across classes implementing the same interface (as opposed to "vertical" sharing through inheritance).

What key new features does it support? (for instance Splititerators)

java.util.Collection<T>.stream()

What other alternatives were there to support those language features? For example, why not create a new interface SplitIterable that extends Iterable?

You could opt for entirely new interfaces, and continue with the associated static helper class (e.g. Collection<T> interface and its Collections helper class). This wouldn't be terrible - in fact, one could argue that default methods are purely a syntactic sugar on top of static methods*. However, default methods generally provide for better readability.

What would be the impact of implementing those alternatives (proliferation of interfaces?)

You would end up with a less consistent library, and a less readable language, but it wouldn't be the end of the world. A bigger concern, as pointed out by Joachim Sauer, is that interface implementations would have no way to override implementation from the static helper class. That would take away flexibility.

Should I provide a default implementation for a method in the first edition of interface when it is possible to implement it as a composition of other methods?

You should do it only if you need to share implementation "horizontally". If a method provides essential behavior of the implementation, do not provide a default for it.

* This would be an oversimplification, because default methods remain virtual. Thanks Brian Goetz for the comment.

Community
  • 1
  • 1
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 5
    There's one big difference between static helper methods and default methods: subclasses/implementors can implement the methods to replace the default method with a better implementation. That's actually quite common for Collection subclasses. – Joachim Sauer Mar 31 '16 at 14:25
  • 1
    One benefit of having a helper class alongside the interface is the explicit distinction between the essential methods of the interface that must be implemented and helper methods, that are just composition of essential methods. By putting the helper methods inside the interface we are actually suggesting the implementor to implement them. By the way, extension methods in c# is among other things a nice way to hide the inconvenience of helper classes – ironstone13 Mar 31 '16 at 14:31
  • 5
    Java's default methods are _virtual_ and _declaration-site_ (as opposed to C#'s extension methods which are _static_ and _use-site_.) Virtual allows subclasses to override with a better implementation; declaration-site allows API designers to extend their APIs after publication, while retaining control over the APIs. – Brian Goetz Mar 31 '16 at 15:01
  • 1
    @BrianGoetz Thanks for the comment! It's nice to hear from someone who actually designs the language, not just uses it :-) – Sergey Kalinichenko Mar 31 '16 at 15:08
  • 2
    @ironstone13: you still can recognize the methods you should implement by the fact that they are not `default` methods. But `default` methods still can be overridden, if there is an opportunity for a more suitable implementation. The implementor should know that, otherwise there is no reason to override a `default` method. On the other hand, if a helper method is not intended to be overridden at all, a `static` method might be more appropriate. Keep in mind that the helper methods placed in a different class are all `static` anyway, so it doesn’t matter in which class you place them… – Holger Mar 31 '16 at 15:11
  • @BrianGoetz, C# extension methods are not entirely use-site, for example, most of the extension mehotds for System.Collections.Generic.IEnumerable are placed in System.Linq.IEnumerable - and both reside under one namespace, even though in different assemblies – ironstone13 Mar 31 '16 at 15:16