| 

.NET C# Java Javascript Exception

6
Vor ein paar Tagen bin ich über einen Artikel bei heise Developer gestolpert, der die Neuerungen für Entwickler in Java 8 zum Gegenstand hat. Eines der neuen Features hat dabei bei mir spontan ungläubiges Erstaunen ausgelöst: die Möglichkeit, Methoden in Interfaces mit default-Implementierungen auszustatten. Z.B. so:

interface Iterable<T> ... {
...
void forEach(Consumer<? super T> action) default {
Iterables.forEach(this, action);
}
}

Eigentlich hatte ich gedacht, dass seit den Tagen, als das Constant Interface anti-pattern als solches gebrandmarkt wurde, auch in der Java-Community Konsens darüber herrscht, dass es ein Zeichen guten Designs ist, Interface und Implementierung sauber voneinander zu trennen. Und jetzt das...

Was ich befürchte:

  • daß das Feature mißbraucht wird, um eine milde Form von Mehrfachvererbung in Java zu nutzen (von Entwicklern, denen Prinzipien wie "favor composition over inheritance" egal sind)
  • daß Java, immerhin auch in der Lehre eine weit verbreitete Sprache, es OOP-Neulingen damit schwerer macht, den fundamentalen Unterschied zwischen Schnittstelle und Implementierung zu erkennen, zu begreifen und zu verinnerlichen

Immerhin erkennt der Java-Compiler einen potentiellen Diamond of Death.

Nicht daß mich einer falsch versteht: die Motivation der Java-Designer für dieses Feature habe ich schon verstanden. Sie wollen Iterable & Co. um eine Reihe nützlicher Methoden erweitern, ohne existierenden Code zu brechen, in dem diese Interfaces implementiert werden. Aber letztlich ist das doch das selbe Problem, das das .NET-Team bei der Einführung von LINQ und Lambdas in .NET 3.5 hatte. Und ich finde die dort gefundene Lösung der Erweiterungsmethoden um einiges gelungener:

  • An Syntax und Semantik von Interfaces hat sich nichts geändert.
  • Die Nutzung der Erweiterungen folgt einem opt-in-Prinzip. Wenn ich die Erweiterungen nicht brauche und auch nicht will, dass mir IntelliSense für eine IEnumerable<T>-Instanz eine lange Liste von Methoden anbietet, die ich gar nicht brauche, dann importiere ich einfach nicht System.Linq, und Ruhe ist.
  • Man kann - wenn schon, denn schon - nicht nur Interfaces erweitern, sondern auch Klassen.

Interessanterweise scheint sich die Syntax für die Java-Default-Methoden im Laufe der Zeit etwas gewandelt zu haben. Wenn ich mir http://stackoverflow.com/questions/7857832/are-defaults-in-jdk-8-a-form-of-multiple-inheritance-in-java ansehe, so scheint in einer früheren Version etwas in der Art geplant gewesen zu sein (ich greife obiges Beispiel auf):

interface Iterable<T> ... {
...
void forEach(Consumer<? super T> action) default Iterables.forEach;
}
}

Das wäre schon um einiges näher dran am Ansatz von .NET - immerhin liegt die Implementierung damit schon mal in einer eigenen Klasse, im Interface wird nur noch darauf verwiesen. Aber statt noch einen Schritt weiter zu gehen und die Deklaration der "Verlinkung" vom Interface in die Implementierungsklasse zu schieben (wie es bei den .NET-Erweiterungsmethoden der Fall ist), scheint man gerade in die andere Richtung gegangen zu sein und auf den Zwang zur Extra-Klasse verzichtet zu haben.

Weiß jemand, warum man sich bei Java so entschieden hat? Und vor allem: was haltet ihr von dem neuen Feature? Teilt ihr meine Bedenken, oder seht ihr das anders?
java oop extension-methods interface
13.08.2013
Matthias Hlawatsch 13,2k 4 9