Interfaces (Schnittstellen) in Java


Wir behandeln in diesem Beitrag die wichtigsten Eigenschaften vom Interfaces in Java.

Dabei soll dieser allgemeine Beitrag über Interfaces als Übersicht dienen. Ausführliche Erklärungen zu den einzelnen Themen findet ihr in den jeweiligen Themenbeitrag:

Was ist ein Interface in Java?

In Java kann eine abgeleitete Klasse nur genau eine Vaterklasse haben. Das Erben von mehr als einer Superklasse (Mehrfachvererbung) ist nicht möglich.

Den Entwicklern der Programmiersprache Java war Mehrfachvererbung bekannt und auch die Nachteile die sie mit sich bringt. Ganz auf Mehrfachvererbung verzichten wollten sie aber nicht und schafften einen Mittelweg: das Interface.

Interfaces können als Ersatzkonstrukt für Mehrfachvererbung gesehen werden. Eine Klasse kann mehrere Interfaces implementieren, d.h. ihr können mehrere Schnittstellen zur Verfügung gestellt werden. Jede dieser Schnittstellen (Interfaces) muss aber von der Klasse vollständig implementiert werden.

Ein Interface ist eine Schnittstelle, über die einer Klasse bestimmte Funktionen zur Verfügung gestellt werden. Um die Funktionen nutzen zu können, müssen sie aber erst von der Klasse implementiert werden. Das Interface gibt nur den Rahmen (die Methodendeklarationen) vor.

Interfaces können als eine besondere Form einer Klasse angesehen werden. Sie enthalten ausschließlich Konstanten und abstrakte Methoden. Die abstrakten Methoden müssen von der Klasse implementiert werden, der das Interface zugewiesen wird.

Mehrfachimplementierung – Implementieren von mehreren Interfaces

In Java gibt es keine Mehrfachvererbung. Als Alternative zur Mehrfachvererbung können wir auf Interfaces zurückgreifen, da eine Klasse mehr als ein Interface implementieren kann.

Die Mehrfachimplementierung von verschiedenen Interfaces ist in Java durchaus üblich. Dabei muss jede Klasse für jedes Interface alle darin deklarierten Methoden implementieren.

Implementiert eine Klasse ein Interface, wird sie dabei automatisch zu diesem Interface-Datentyp kompatibel. Eine Klasse kann daher zu mehreren Datentypen kompatibel sein.

In Java ist eine Klasse kompatibel zu:

  • dem Datentyp ihrer eigenen Klasse
  • den Datentypen ihrer n-Superklassen
  • den Datentypen ihrer m-Interfaces, die sie implementiert

Somit ist eine Klasse zu (n + m + 1) Datentypen kompatibel.

Vererbung von Interfaces in Java

In Java vererbt eine Vaterklasse ihre Interfaces an ihre Tochterklassen. Sind von der Vaterklasse bereits alle Interface-Methoden implementiert worden, muss in den Tochterklassen keine Methode zusätzlich nachimplementiert werden.

Es ist aber erlaubt, dass die Tochterklassen eigene Versionen der Interface-Methoden implementieren, falls dies erforderlich sein sollte.

Wir möchten nun das Vererben von Interfaces in Java testen, dazu schreiben wir eine kleine Anwendung, bei der das Interface der Vaterklasse an die abgeleitete Tochterklasse vererbt wird. Die Tochterklasse soll dabei noch ein zweites Interface zusätzlich implementieren und eine Interface-Methode der Vaterklasse überlagern.

Ableiten von Interfaces in Java

In Java kann ein Interface seine Eigenschaften an andere Interfaces vererben. Wie bei der normalen Vererbung erbt dabei das abgeleitete Interface alle Methoden und Konstanten des Basis-Interfaces.

Soll eine Klasse ein abgeleitetes Interface implementieren, muss sie alle Methoden dieses Interfaces und des übergeordneten Super-Interfaces implementieren. Wie Interfaces von anderen Interfaces ableitet erfahrt ihr in unserem Beitrag: Ableiten von Interfaces in Java.

Konstanten in Java verfügbar machen – Interface vs. import static

Komplexe Java-Anwendungen müssen oft auf Konstanten zugreifen. Dabei kann es vorkommen, dass viele Konstanten in mehreren Klassen zur Verfügung stehen müssen.

Möchte man in Java oft benötigte Konstanten in unterschiedlichen Klassen wiederverwenden, dann bieten sich hierfür die folgenden beiden Vorgehensweisen an:

  1. Alle Konstanten mit Hilfe eines Interfaces den Klassen zur Verfügung stellen oder
  2. Nur die benötigten Konstanten mittels import static in den Klassen verfügbar machen

Wir möchten in dem Beitrag: Konstanten in Java verfügbar machen beide Vorgehensweisen vorstellen. Zur Info vorab: Der Ansatz, Konstanten mit Hilfe des import static Klassen gezielt zur Verfügung zu stellen, ist der bessere Programmierstil, wenngleich das Nutzen eines Interfaces auch eine, unter Java-Programmierern, sehr weit verbreitete Vorgehensweise ist.

Mit Hilfe von Interfaces Funktionszeiger in Java nachbilden

In Java können Interfaces zur Nachbildung von Funktionszeigern verwendet werden. Diese Anwendungsart von Interfaces ist besonders nützlich, wenn die Konfigurationsanforderungen einer Methode nicht durch die Übergabe von Variablen erfüllt werden können.

Die hier beschriebene Vorgehensweise wird bspw. bei Callback-Funktionen benötigt, wie sie für die Programmierung von grafischen Benutzeroberflächen verwendet werden.

Die Vorgehensweise für die Nachbildung von Funktionszeigern mittels Interfaces

Als erstes wird ein Interface definiert, in dem die erforderliche Methode abstrakt deklariert wird.

Dieses Interface wird anschließend von unterschiedlichen Klassen implementiert und dabei wird die Interface-Methode jeweils so umgesetzt, dass in ihr die erforderlichen Berechnungen durchgeführt werden.

Somit verfügt jede Klasse über eine eigene, an die Konfigurationsanforderungen angepasste, Implementierung der Interface-Methode. Werden nun Instanzen dieser Klassen erzeugt und an die zu konfigurierende Methode übergeben, so wird in der zu konfigurierenden Methode jeweils genau die Methodenversion der jeweils instanzierten Klasse ausgeführt. Die jeweilige Methodenversion kann dadurch den Konfigurationsanforderungen entsprechend implementiert werden.

Diese Vorgehensweise kann am besten mit der Beispielanwendung, wie man mit Hilfe von Interfaces Funktionszeiger in Java nachbildet, verstanden werden.

Interface als Flag nutzen am Beispiel des Cloneable-Interfaces in Java

In Java können Interfaces als logische An- und Aus-Schalter verwendet werden, die zur Kompilier- und Laufzeit abgefragt werden können.

In dem Beitrag: Interface als Flag nutzen möchten wir ein solches Flag-Interface am Beispiel des Interface Cloneable vorstellen. Das Cloneable-Interface ist ein Flag (An/Aus-Schalter) für die in der Klasse Object implementierte Methode clone(). Die Methode clone() ist in der Object-Klasse native implementiert, um die Performance zu verbessern.

Das Cloneable-Interface wird als Indikator genutzt, mit dem überprüft wird, ob eine abgeleitete Klasse die Fähigkeit besitzt eine eigene Objektkopie herzustellen. Ist das Cloneable-Interface in der abgeleiteten Klasse nicht implementiert, wird beim Aufruf von clone() eine CloneNotSupportedException ausgelöst.

Dadurch wird dem Entwickler mitgeteilt, dass die abgeleitete Klasse nicht über die Fähigkeit verfügt eigene Objekte elementweise zu kopieren (clonen).

Implementierung des Interface an die Default-Klasse delegieren in Java

In dem Beitrag: Implementierung des Interface an die Default-Klasse delegieren werden wir eine Default-Implementierung eines Interfaces entwickeln und die Funktionalität dieser Default-Implementierung in einer Delegationsklasse wiederverwenden.

Die Idee dabei ist, die Vorteile eines Interfaces (Mehrfachverwendung in unterschiedlichen Klassenhierarchien) mit denen einer Klasse (Teilimplementierung der Methoden, Verwendung von Konstruktoren und statischen Elementen) zu kombinieren.

Dabei stellt ein Interface die Methodendeklarationen zur Verfügung und eine Default-Klasse implementiert diese Methoden als Referenzimplementierung (Default-Implementierung).

Der folgende Link führt euch zurück zum Programmierkurs.

Comments 2

  1. Pingback: Vererbung und Polymorphismus in Java

  2. Pingback: Einführung in Java Design Patterns (Software Entwurfsmuster)

Hinterlasse eine Antwort

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *