Tit   Inh   Ind   1   2   3   4   5   6   7   8   9   10   11   12   13   14   15   16   17   18   19   20   21   22   23   24   25   26   27   28   29   30   31   32   <<   <   >   >> 

7.7 Interfaces



Es wurde bereits erwähnt, daß es in Java keine Mehrfachvererbung von Klassen gibt. Die möglichen Schwierigkeiten beim Umgang mit mehrfacher Vererbung und die Einsicht, daß das Ererben von nichttrivialen Methoden aus mehr als einer Klasse in der Praxis selten zu realisieren ist, haben die Designer dazu veranlaßt, dieses Feature nicht zu implementieren. Andererseits sah man es sehr wohl als wünschenswert an, Methodendeklarationen von mehr als einer Klasse zu erben und hat mit den Interfaces ein Ersatzkonstrukt geschaffen, das genau dieses Feature bietet.

7.7.1 Definition eines Interfaces

Ein Interface ist eine besondere Form einer Klasse, die ausschließlich abstrakte Methoden und Konstanten enthält. Anstelle von class wird zur Definition eines Interfaces das Schlüsselwort interface verwendet. Alle Methoden sind daraufhin standardmäßig abstrakt. Ein Interface kann allerdings keine Konstruktoren enthalten.

Das folgende Listing definiert ein Interface Fortbewegungsmittel, das die Methoden kapazitaet und kilometerPreis definiert:

001 public interface Fortbewegungsmittel
002 {
003   public int kapazitaet();
004   public double kilometerPreis();
005 }
Listing 7.28: Definition eines Interfaces

7.7.2 Verwendung von Interfaces

Was bei der Vererbung von Klassen als Ableitung bezeichnet wird, nennt man bei Interfaces Implementierung. Durch das Implementieren eines Interfaces verpflichtet sich die Klasse, alle Methoden, die im Interface definiert sind, zu implementieren. Fehlt eine Methode, so gibt es einen Compilerfehler. Die Implementierung eines Interfaces wird durch das Schlüsselwort implements bei der Klassendefinition angezeigt.

Als Beispiel wollen wir die Klasse Auto um das neue Interface Fortbewegungsmittel erweitern und die Methoden kapazitaet und kilometerPreis implementieren:

001 public class Auto
002 implements Fortbewegungsmittel
003 {
004   public  String name;
005   public  int    erstzulassung;
006   public  int    leistung;
007   private int    anzahlSitze;
008   private double spritVerbrauch;
009   private double spritPreis;
010 
011   public double kapazitaet()
012   {
013     return anzahlSitze;
014   }
015 
016   public double kilometerPreis()
017   {
018     return spritVerbrauch*spritPreis/100;
019   }
020 
021 }
Listing 7.29: Implementieren eines Interfaces

 Beispiel 

Ebenso wie die Klasse Auto könnte auch jede andere Klasse das Interface Fortbewegungsmittel implementieren und Konkretisierungen der beiden Methoden vornehmen. Nützlich ist dies insbesondere für Klassen, die in keinem direkten Zusammenhang mit der Klasse Auto und ihrer Vererbungshierarchie stehen. Um ihr gewisse Eigenschaften eines Fortbewegungsmittels zu verleihen, könnte also beispielsweise auch die Klasse Teppich dieses Interface implementieren.

Eine Klasse kann auch dann ein Interface implementieren, wenn sie bereits von einer anderen Klasse abgeleitet ist. In diesem Fall erbt die neue Klasse wie gewohnt alle Eigenschaften der Basisklasse und hat zusätzlich die Aufgabe, die abstrakten Methoden des Interfaces zu implementieren.

 Hinweis 

Das folgende Interface Sammlerstueck mag bei gewöhnlichen Autos keine Anwendung finden, ist bei einem Oldtimer aber durchaus sinnvoll:

001 public Interface Sammlerstueck
002 {
003   public double sammlerWert();
004   public String bisherigeAusstellungen();
005 }
006 
007 public class Oldtimer
008 extends Auto
009 implements Sammlerstueck
010 {
011   //...
012 }
Listing 7.30: Definition eines weiteren Interfaces

 Beispiel 

Da ein Sammlerstueck aber durchaus auch in ganz anderen Vererbungshierarchien auftauchen kann als bei Autos (beispielsweise bei Briefmarken, Schmuck oder Telefonkarten), macht es keinen Sinn, diese Methoden in den Ableitungsbäumen all dieser Klassen wiederholt zu deklarieren. Statt dessen sollten die Klassen das Interface Sammlerstueck implementieren und so garantieren, daß die Methoden sammlerWert und bisherigeAusstellungen zur Verfügung stehen.

7.7.3 Implementieren mehrerer Interfaces

Eine Klasse kann nicht nur ein einzelnes Interface, sondern eine beliebige Anzahl von ihnen implementieren. So ist es beispielsweise problemlos möglich, eine aus Flugzeug abgeleitete Klasse Doppeldecker zu definieren, die sowohl Sammlerstueck als auch Fortbewegungsmittel implementiert:

001 public class Doppeldecker
002 extends Flugobjekt
003 implements Fortbewegungsmittel, Sammlerstueck
004 {
005   //...
006 }
Listing 7.31: Implementieren mehrerer Interfaces

Die Klasse Doppeldecker muß dann alle in Sammlerobjekt und Fortbewegungsmittel deklarierten Methoden implementieren.

7.7.4 Interfaces sind Klassen

Interfaces besitzen zwei wichtige Eigenschaften, die auch Klassen haben:

Es macht also Sinn, ein Interface als eine Typvereinbarung anzusehen. Eine Klasse, die dieses Interface implementiert, ist dann vom Typ des Interfaces. Wegen der Mehrfachvererbung von Interfaces kann eine Instanzvariable damit insbesondere mehrere Typen haben und zu mehr als einem Typen zuweisungskompatibel sein.

 Hinweis 

7.7.5 Konstanten in Interfaces

Neben abstrakten Methoden können Interfaces auch Konstanten, also Variablen mit den Attributen static und final, enthalten. Wenn eine Klasse ein solches Interface implementiert, erbt es gleichzeitig auch all seine Konstanten. Es ist auch erlaubt, daß ein Interface ausschließlich Konstanten enthält.

Dieses Feature kann zum Beispiel nützlich sein, wenn ein Programm sehr viele Konstanten definiert. Anstatt diese in ihren korrespondierenden Klassen zu belassen und mit Klasse.Name aufzurufen, könnte ein einzelnes Interface definiert werden, das alle Konstantendefinitionen vereinigt. Wenn nun jede Klasse, die eine der Konstanten benötigt, dieses Interface implementiert, so stehen alle darin definierten Konstanten direkt zur Verfügung und können ohne die Qualifizierung mit einem Klassennamen aufgerufen werden.

 Tip 

7.7.6 Beispiele aus der Java-Klassenbibliothek

Die Java-Klassenbibliothek definiert und implementiert selbst eine ganze Reihe von Interfaces. Drei von ihnen sollen hier kurz vorgestellt werden.

Runnable

Das Interface Runnable wird zur Implementierung von Threads verwendet, und zwar insbesondere dann, wenn die betreffende Klasse selbst nicht direkt aus Thread abgeleitet werden kann. Runnable deklariert lediglich die Methode run, deren Rumpf den ausführbaren Code des Threads enthält. Der Umgang mit Threads wird in Kapitel 10 erklärt.

Enumeration

Das Interface Enumeration wird zur Deklaration von Enumeratoren verwendet. Enumeratoren dienen dazu, alle Elemente von Kollektionen (z.B. Hashtable oder Vector) nacheinander zu durchlaufen. Enumeration definiert die Methoden nextElement und hasMoreElements. Sie dienen dazu, das nächste Element der Kollektion zu holen bzw. zu testen, ob weitere Elemente vorhanden sind.

Cloneable

Dieses Interface ist etwas untypisch, denn es besitzt weder Methoden noch Konstanten. Es dient lediglich dazu, dem Compiler anzuzeigen, daß eine Klasse die Methode clone unterstützt und damit die Fähigkeit besitzt, sich selbst zu kopieren.


 Tit   Inh   Ind   1   2   3   4   5   6   7   8   9   10   11   12   13   14   15   16   17   18   19   20   21   22   23   24   25   26   27   28   29   30   31   32   <<   <   >   >> 
Go To Java 2, Addison Wesley, Version 1.0.2, © 1999 Guido Krüger, http://www.gkrueger.com