Die kurze Antwort lautet: Es ist sicher, wenn Sie sie sicher verwenden :)
Die snarky Antwort: Sag mir, was du mit Eigenschaften meinst, und vielleicht gebe ich dir eine bessere Antwort :)
In aller Ernsthaftigkeit ist der Begriff "Merkmal" nicht genau definiert. Viele Java-Entwickler sind mit Merkmalen am besten vertraut, da sie in Scala ausgedrückt werden. Scala ist jedoch weit davon entfernt, die erste Sprache zu sein, die Merkmale aufweist, entweder im Namen oder in der Wirkung.
In Scala sind Merkmale beispielsweise zustandsbehaftet (können var
Variablen enthalten). In der Festung sind sie reines Verhalten. Javas Schnittstellen zu Standardmethoden sind zustandslos. Bedeutet das, dass sie keine Eigenschaften sind? (Hinweis: Das war eine Trickfrage.)
Auch in Scala werden Merkmale durch Linearisierung zusammengesetzt. Wenn die Klasse A
Merkmale X
und erweitert Y
, bestimmt die Reihenfolge, in der X
und Y
gemischt werden, wie Konflikte zwischen X
und Y
gelöst werden. In Java ist dieser Linearisierungsmechanismus nicht vorhanden (er wurde teilweise abgelehnt, weil er zu "un-Java-ähnlich" war.)
Der Hauptgrund für das Hinzufügen von Standardmethoden zu Schnittstellen war die Unterstützung der Schnittstellenentwicklung , aber wir waren uns bewusst, dass wir darüber hinausgehen. Ob Sie dies als "Interface Evolution ++" oder "Traits--" betrachten, ist eine Frage der persönlichen Interpretation. Um Ihre Frage zur Sicherheit zu beantworten ... Solange Sie sich an das halten, was der Mechanismus tatsächlich unterstützt, anstatt zu versuchen, ihn auf etwas zu dehnen, das er nicht unterstützt, sollte es Ihnen gut gehen.
Ein wichtiges Entwurfsziel war, dass Standardmethoden aus Sicht des Clients einer Schnittstelle nicht von "normalen" Schnittstellenmethoden zu unterscheiden sind. Die Standardeinstellung einer Methode ist daher nur für den Designer und Implementierer der Schnittstelle interessant .
Hier sind einige Anwendungsfälle, die innerhalb der Entwurfsziele liegen:
Schnittstellenentwicklung. Hier fügen wir einer vorhandenen Schnittstelle eine neue Methode hinzu, die eine sinnvolle Standardimplementierung in Bezug auf vorhandene Methoden auf dieser Schnittstelle aufweist. Ein Beispiel wäre das Hinzufügen der forEach
Methode zu Collection
, wobei die Standardimplementierung in Bezug auf die iterator()
Methode geschrieben wird.
"Optionale" Methoden. Hier sagt der Designer einer Schnittstelle: "Implementierer müssen diese Methode nicht implementieren, wenn sie bereit sind, mit den damit verbundenen Einschränkungen der Funktionalität zu leben." Zum Beispiel Iterator.remove
wurde eine Standardeinstellung gegeben, die wirft UnsupportedOperationException
; Da die überwiegende Mehrheit der Implementierungen Iterator
dieses Verhaltens ohnehin aufweist, ist diese Methode standardmäßig im Wesentlichen optional. (Wenn das Verhalten von AbstractCollection
als Standardwert für ausgedrückt würde Collection
, könnten wir dasselbe für die mutativen Methoden tun.)
Convenience-Methoden. Dies sind Methoden, die nur der Einfachheit halber dienen und wiederum im Allgemeinen in Form von nicht standardmäßigen Methoden für die Klasse implementiert werden. Die logger()
Methode in Ihrem ersten Beispiel ist ein vernünftiges Beispiel dafür.
Kombinatoren. Hierbei handelt es sich um Kompositionsmethoden, mit denen neue Instanzen der Schnittstelle basierend auf der aktuellen Instanz instanziiert werden. Zum Beispiel sind die Methoden Predicate.and()
oder Comparator.thenComparing()
Beispiele für Kombinatoren.
Wenn Sie eine Standardimplementierung bereitstellen, sollten Sie auch eine Spezifikation für die Standardimplementierung angeben (im JDK verwenden wir hierfür das @implSpec
Javadoc-Tag), damit Implementierer besser verstehen, ob sie die Methode überschreiben möchten oder nicht. Einige Standardeinstellungen, wie Convenience-Methoden und Kombinatoren, werden fast nie überschrieben. andere, wie optionale Methoden, werden häufig überschrieben. Sie müssen genügend Spezifikationen (nicht nur Dokumentation) darüber bereitstellen, was die Standardeinstellung verspricht, damit der Implementierer eine vernünftige Entscheidung darüber treffen kann, ob er sie überschreiben muss.