Interface (Java)

Aus Byte-Welt Wiki
Wechseln zu: Navigation, Suche

In Java ist ein Interface eine Schnittstelle die zu implementierende Methoden vorgibt.

Ein Interface wird üblicherweise in einer eigenen Java-Datei gespeichert. Wenn das Interface öffentlich (public) ist, muss der Name der Datei dem Namen des Interfaces entsprechen. Wie Klassen können auch Interfaces in Packages eingeteilt werden. Mit Interfaces lassen sich für Klassen, die thematisch nichts gemeinsam haben, Gemeinsamkeiten definieren.

Syntax

Basis

Der Syntax eines Interfaces ähnelt einer Klasse:

[public | protected | private] interface (Name){
  public void methodeA();
 
  public int methodeB( boolean x );
 
  public String methodeC( String x, float y );
 
  public static final int KONSTANTE_A = 3;
}
  • Kopf
    • Mit einem Modifier wird die Sichtbarkeit des Interfaces geregelt.
    • Das Schlüsselwort interface zeigt an, dass nun ein Interface definiert wird.
    • Der Name des Interfaces muss mit einem Buchstaben beginnen, und kann dann mit jedem beliebigen Buchstaben, Ziffer und auch einigen Sonderzeichen erweitert werden.
  • Rumpf
    • Der Rumpf wird durch geschweifte Klammern gebildet
    • Im Rumpf sind Methodenköpfe definiert. Es ist aber nicht erlaubt die Methoden zu implementieren (Methodenrümpfe sind also nicht erlaubt)
    • Jede definierte Methode ist automatisch public und abstract, das Schlüsselwort "public" ist eigentlich redundant, wird aber trotzdem oft ausgeschrieben.
    • Es können auch Konstanten im Rumpf definiert werden. Alle Variablen im Rumpf sind automatisch public, static und final.

Vererbung

Ein Interface kann von beliebig vielen anderen Interfaces erben. Dabei wird das Schlüsselwort extends eingesetzt:

public interface Child extends Mother, Father{
   ...
}

Das Kind-Interface definiert damit alle Methoden und Konstanten, welche schon in den Elter-Interfaces definiert waren. Die Vererbung erlaubt es auch, überall dort das Kind-Interface einzusetzen, wo nur ein Elter-Interface erwartet und benötigt wird.

Interfaces verwenden

Interfaces werden genau gleich wie Klassen verwendet: verschiedene Methoden können jederzeit aufgerufen werden.

Ist zum Beispiel folgendes Interface gegeben...

public interface Something{
  public String doSomething( String somewhat );
}

... kann es in einer Methode folgendermassen verwendet werden:

public String callSomething( Something something ){
  return something.doSomething( "abc" );
}

Interfaces implementieren

Interfaces werden von Klassen implementiert. Das bedeutet, dass eine Klasse von einem Interface "erbt", und zu den vom Interface definierten Methodenköpfen, beliebige Methodenrümpfe angibt.

Eine Klasse, sofern sie nicht abstrakt ist, muss alle definierten Methoden implementieren. Es ist auch nicht möglich die Methodenköpfe abzuändern, da ein möglicher Aufrufer nichts von den abgeänderten Methoden wüsste.

Es ist möglich, dass eine Klasse mehr als ein Interface implementiert. In diesem Fall werden die Interfaces durch Kommas getrennt angegeben:

public class Klasse implements InterfaceA, InterfaceB{
  ...
}

Beispiel

In einem Textadventure betritt der Spieler einen dunklen Raum. In diesem Raum ist ein Haustier, doch es ist nicht bekannt welches. Softwaremässig lässt sich das folgendermassen abbilden:

Ein Interface Haustier beschreibt das unbekannte Wesen.

public interface Haustier{
  // setzt den Besitzer dieses Haustiers
  public void setBesitzer( String besitzer );
 
  // Das typische Geräusch, das dieses Haustier macht
  public String laut();
}

Ein typischer Vertreter der Haustiere ist eine Katze.

public class Katze implements Haustier{
  public void setBesitzer( String besitzer ){
    // ignorieren, ich jage lieber Mäuse
  }
 
  public String laut(){
    return "Miau";
  }
}

Ein eher exotisches Haustier ist hingegen der sprechende Papagei.

public class Papagei implements Haustier{
  private String besitzer;
 
  public void setBesitzer( String besitzer ){
    this.besitzer = besitzer;
  }
 
  public String laut(){
    return "Krächtz, Hallo " + besitzer + ", Krächtz";
  }
}

Das Abenteuer beginnt. Zuerst wird eine Haustier-Variable initialisiert, dann wird der "dunkle Raum" betreten.

public void abenteuer(){
  Haustier haustier;
  if( Math.random() > 0.5 )
    haustier = new Papagei();
  else
    haustier = new Katze();
 
  haustier.setBesitzer( "Emma" );
  dunklerRaum( haustier );
}

Es ist nicht bekannt, welches Haustier noch in dem Raum ist. Das Interface Haustier gibt aber Zugriff auf alle Informationen, welche für die Darstellung des Raumes notwendig sind.

public void dunklerRaum( Haustier haustier ){
  System.out.println( "Du betrittst einen dunklen Raum." );
  System.out.println( "Plötzlich hörst du ein Geräusch:" );
  System.out.println( haustier.laut() );
  System.out.println( "Was das wohl ist?" );
}

Sinn von Interfaces

Interfaces sind ein wichtiges Konzept von Java, aber wofür kann man sie einsetzen?

Module

Module können unterschiedlichste Dinge sein. Einzelne Klassen können Module sein, eine Gruppe von Klassen (wie z.B. Swing) kann ein Modul sein, ganze Programme oder Libraries sind Module. Module können sogar verschachtelt sein. Eines ist aber allen Modulen gemeinsam: sie sind abgeschlossene, komplette Systeme mit einer klar definierten Funktion. Man weiss nicht, wie sie intern funktionieren, aber man kennt ihre Schnittstellen, und kann so mit ihnen arbeiten.

Die deutsche Übersetzung von "Interface" ist "Schnittstelle". Interfaces eignen sich um verschiedene Module zu verbinden. Die vom Modul definierten Interfaces werden vom Benutzer implementiert, so sprechen Benutzer und Modul dieselbe "Sprache", und können interagieren.

Ein Beispiel: das Modul JTable benutzt das Interface TableModel um die Daten, die es zeichnen wird, zu finden. Dem Model JTable ist es egal, wie die Daten gespeichert werden, es ist nur daran interessiert, dass es auf die Daten zugreiffen kann.

Abstraktion

Interfaces helfen auch dabei, nur die wesentlichen Dinge zu betrachten. Man kann für jeden Algorithmus eines oder mehrere Interfaces beschreiben, die genau die Methoden enthalten, welche unbedingt benötigt werden. Ein Beispiel ist ein Sortieralgorithmus: er muss nur wissen, wie man zwei Objekte vergleicht, und wie das grössere Objekt bestimmt werden kann. Entsprechend wird ein Interface Comparator definiert, welches genau dies macht. Dieses Comparator-Interface kann nun für unterschiedlichste Objekttypen implementiert werden. Ein Comparator vergleicht Dateien anhand ihrer Grösse, ein anderer vergleicht Bildschirme anhand ihrer Auflösung. Dem Sortieralgorithmus bleiben diese Details verborgen, er kann sich auf seine Hauptaufgabe, das Sortieren, konzentrieren.