javaseiten.de   |   Version 0.6
 

1.9. Interfaces

Ein Interface ist eine besondere Form einer Klasse (Schnittstellen-Klasse). Wie in Abschnitt 1.8 beschrieben, kann eine abstrakte Klasse neben konkreten Methoden (mit Methodenkörper) auch abstrakte Methoden (ohne Methodenkörper) besitzen. Ein Interface hingegen kann abstrakte Methoden aber keine konkreten Methoden deklarieren (ein Interface besitzt keine Implementierung).

1.9.1. Deklaration

Es wird zwischen zwei unterschiedlichen Interfacedeklarationen unterschieden: Normale Interfacesdeklaration und Deklaration eines Annotationstyps (siehe dazu Abschnitt 2). Um eine (normale) Klasse zu deklarieren, wird das Schlüsselwort class verwendet, wohingegen eine normale Interfacedeklaration die Angabe des Schlüsselwortes interface verlangt:

InterfaceModifiers_opt interface InterfaceName2 extends InterfaceName1, ..., 
                                                        InterfaceNameN
{
  ...
}

Interfaces können auch innerhalb von weiteren Interfaces angeordnet sein und werden als eingebettete oder innere Interfaces bezeichnet. Auch Klassen können weitere Klassen enthalten (siehe dazu Abschnitt 1.10). In diesem Abschnitt sollen Top-Level-Interfaces behandelt werden, die nicht in andere Interfaces eingebettet sind (wenn im folgenden von Interfaces gesprochen wird, soll von Top-Level-Interfaces ausgegangen werden). Als Modifiers für Interfaces können public und abstract gewählt werden. Wird bei der Deklaration des Interfaces public verwendet, ist das Interface, genauso wie bei Klassen, paketübergreifend nutzbar. Ohne den genannten Modifier ist die Sichtbarkeit des Interfaces auf das zugehörige Paket beschränkt. Ein Interface ist implizit abstrakt. Der Modifier abstract kann angegeben werden, wobei dessen Verwendung bei einer Interfacedeklaration als veraltet eingestuft ist und daher weggelassen werden sollte. Durch die Verwendung des Schlüsselwortes extends kann ein Interface ein anderes bestehendes Interface erweitern. Im Gegensatz zu einer Klasse, bei der nur eine Erweiterung einer einzigen Klasse möglich ist, kann ein Interface mehrere Interfaces erweitern (ein Interface kann mehrere direkte Superinterfaces besitzen). Die Interfaces die erweitert werden sollen, können nach dem Schlüsselwort extends angegeben werden; sie werden durch Kommata voneinander getrennt.

1.9.2. Körper des Interfaces

Innerhalb des Körpers des Interfaces, also innerhalb des Klammerpaares "{}", können abstrakte Methoden und Konstanten deklariert werden. Die genannten Mitglieder des Interfaces werden als implizit public angesehen. Der Modifier kann demzufolge auch weggelassen werden. Weiterhin ist auch jede Methode eines Interfaces implizit abstrakt. Die Deklaration einer Methode mit dem Modifier abstract ist erlaubt. Bei Interfaces gilt weiterhin, dass jedes deklarierte Feld neben public auch implizit static und final ist. Ein Feld eines Interfaces ist damit eine Konstante. Das folgende kurze Listing definiert ein Interface, dessen Körper die Konstante PI und zwei (abstrakte) Methoden beinhaltet.

Listing 1.36. InterfaceExampleA.java

/* InterfaceExampleA.java */

public interface InterfaceExampleA {
  
  public static final double PI = 3.14159;
  
  public double circumference(double radius);
  public double area(double radius);
}

Im vorausgegangenen Quelltext wurden public und für das Feld zusätzlich static und final verwendet. Bei den beiden Methoden wurde auf den Modifier abstract verzichtet. Die im Beispiel verwendeten Modifier könnten wie erwähnt gänzlich weggelassen werden, da diese automatisch angenommen werden und der Java-Compiler in der zu erzeugenden Klassendatei die entsprechenden Werte setzt (es ist ein "Matter of Style", welche Modifier bei der Deklaration von Feldern und Methoden verwendet bzw. weggelassen werden). Zum Vergleich kann InterfaceExampleA.java auch wie folgt formuliert werden:

/* InterfaceExampleA.java */

public interface InterfaceExampleA {
  
  double PI = 3.14159;
  
  double circumference(double radius);
  double area(double radius);
}

Ein weiteres Interface mit dem Namen InterfaceExampleB soll deklariert werden. Es wird später in einem Beispiel verwendet, um die mehrfache Implementierung eines Interfaces durch eine Klasse zu verdeutlichen. Das Interface enthält lediglich eine abstrakte Methode.

Listing 1.37. InterfaceExampleB.java

/* InterfaceExampleB.java */

public interface InterfaceExampleB {
  
  public double volume(double radius, double height);
}

1.9.3. Implementieren eines Interfaces

Eine Klassendeklaration kann wie in Abschnitt 1.7.2 erläutert eine extends-Klausel enthalten. Es kann sich eine weitere implements-Klausel anschließen, falls die zu erstellende Klasse ein oder mehrere Interfaces implementieren soll.

KlassenModifiers_opt class KlassenName2 
    extends KlassenName1
    implements InterfaceName1, ..., InterfaceNameN
{
  ...
}

Einer Klasse, die Interfaces implementiert, wird eine gewisse Struktur aufgeprägt. Sie ist demnach angehalten die deklarierten abstrakten Methoden eines Interfaces zu implementieren (Methodenkörper mit entsprechenden Anweisungen). Eine Klasse ist jedoch nicht verpflichtet, alle Methoden eines Interfaces zu implementieren. Die Klasse muss aber in diesem Fall als abstract gekennzeichnet werden. Das folgende Beispielprogramm deklariert eine Klasse, die die beiden zuvor angegebenen Interfaces InterfaceExamplA und InterfaceExampleB implementiert. Den drei Methoden circumference, area und volume werden Methodenkörper bereitgestellt. Die implementierten Methoden berechnen Kenngrößen eines geraden Kreiszylinders (Oberfläche, Querschnittsfläche und Volumen).

Listing 1.38. InterfaceExample.java. Die Beispielklasse implementiert zwei Interfaces (Mehrfachimplementierung).

/* InterfaceExample.java */

public class InterfaceExample implements InterfaceExampleA, InterfaceExampleB {
  
  public static final double radius = 3.4;
  public static final double height = 5.0;
  
  public double circumference(double r) {
    double c = 2 * PI * r;
    return c;
  }
  
  public double area(double r) {
    double a = r * r * PI;
    return a;
  }
  
  public double volume(double r, double h) {
    double v = area(r) * h;
    return v;
  }
  
  public static void main(String[] args) {
    InterfaceExample ie = new InterfaceExample();
    double c = ie.circumference(radius);
    double a = ie.area(radius);
    double v = ie.volume(radius, height);
    
    System.out.println("circumference = " + c);
    System.out.println("area = " + a);
    System.out.println("volume = " + v);
  }  
}

Der Quelltext deklariert die zwei Felder radius und height, um die Kenngrößen eines konkreten Zylinders berechnen zu können. Die Konstante PI wird durch das Implementieren des Interfaces InterfaceExampleA verfügbar. Bei den angegebenen Werten für Radius und Höhe erfolgt die Ausgabe:

circumference = 21.362811999999998
area = 36.31678039999999
volume = 181.58390199999997

Das Interface InterfaceExampleB könnte das Interface InterfaceExampleA auch mit Hilfe einer extends-Klausel erweitern.

/* InterfaceExampleB.java */

public interface InterfaceExampleB extends InterfaceExampleA{
  
  public double volume(double radius, double height);
}

Eine Mehrfachimplementierung wie in Listing 1.38 wäre dann nicht nötig. Das durch Erweiterung entstandene Interface verlangt von der Klasse InterfaceExample die Implementierung von insgesamt drei abstrakten Klassen, da zwei vom Superinterface InterfaceExampleA geerbt wurden.

/* InterfaceExample.java */

public class InterfaceExample implements InterfaceExampleB {
...
}

1.9.4. Verschiedenes

 

Verwenden eines Interfacetyps

Durch eine Interfacedeklaration entsteht ein neuer Referenztyp (Interfacetyp). Dir durch Listing 1.36 und Listing 1.37 definierten Interfaces führen zu den beiden neuen Interfacetypen InterfaceExampleA und InterfaceExampleB. Die beiden Referenztypen könnten in einem Java-Quelltext wie folgt verwendet werden:

InterfaceExample  ie  = new InterfaceExample();
InterfaceExampleA iea = new InterfaceExample();
InterfaceExampleB ieb = new InterfaceExample();

Den Variablen ie, iea und ieb wird jeweils eine Referenz auf ein Objekt der Klasse InterfaceExample zugewiesen. Die Typen dieser drei Variablen sind jedoch unterschiedlich. Die beiden letzten Variablen sind von einem Interfacetyp. Dies ist zulässig, da die Klasse InterfaceExample das entsprechende Interface implementiert. Falls eine Referenzvariable mit dem Typ eines Interfaces deklariert wird, kann die Variable Referenzen zu allen Objekten von denjenigen Klassen speichern, welche das Interface implementieren. Mit Hilfe des Schlüsselwortes instanceof kann festgestellt werden, von welcher in Frage kommenden Klasse das Objekt (Instanz) erzeugt wurde, wie z.B.

if (iea instanceof InterfaceExample) {
  ...
}

 

Interface als Konstantensammlung

Das Listing 1.36 enthält die Deklaration einer Konstanten und zwei Methoden. Es ist auch erlaubt, dass innerhalb eines Interfacekörpers ausschließlich Konstanten enthalten sind. Benötigen z.B. mehrere Klassen bestimmte Konstanen, kann ein Interface speziell zur Aufnahme dieser Konstanten erstellt werden. Die entsprechenden Klassen können nun dieses spezielle Interface implementieren und damit stehen ihnen alle Konstanten direkt zur Verfügung.

 

 

 

Diese Seite nutzt Google-Dienste - siehe dazu Datenschutz.

Copyright © 2006, 2007 Harald Roeder