Skip to main content

Interfaces

Mittels Klassen können wir neue Datentypen definieren. Die Felder der Klasse definieren dabei die Daten. Die Methoden definieren welche Operationen auf den Daten verfügbar sind und auch deren konkrete Umsetzung. Durch die Wahl eines Datentyps, wird also sowohl festgelegt, was für Operationen wir zur Verfügung haben, als auch wie diese implementiert sind. Interfaces geben uns die Möglichkeit, die Operationen (das was) von der Implementation (dem wie) zu trennen. Ein Interface spezifiziert einfach eine Menge von Methoden, die ein Datentyp zur Verfügung stellen muss.

Im Folgenden illustrieren wir den Einsatz und Nutzen von Interfaces an einem Beispiel aus der Geometrie. Angenommen, wir möchten eine Zeichenanwendung schreiben. Diese soll verschiedene geometrische Objekte wie Kreise, Rechtecke, etc., zeichnen und manipulieren können. Jedes Objekt soll vergrössert und verkleinert werden können. Zudem soll die Position jedes Objekts geändert werden können.

Dazu definieren wir auf jedem Datentyp die Methode scale(double scaleFactor), die uns das Objekt skalieren lässt. Ein entsprechendes Interface können wir in Java wie folgt definieren:

interface Scalable {
void scale(double scaleFactor);
}

Beachten Sie folgende Punkte:

  • Die Definition ist ähnlich wie bei einer Klasse. Statt des Schlüsselworts class wird aber das Schlüsselwort interface verwendet. Das Interface hat in diesem Beispiel den Namen Scalable.
  • Die Definition der Methode scale besteht aus der kompletten Methodensignatur (also Rückgabewert, Name, Parameter). Die Implementation jedoch fehlt.

Wir definieren uns ein zweites Interface, welche die Methoden für das Positionieren des Objekts zur Verfügung stellt:

interface Movable {
void translate(double x, double y);
void moveToOrigin();
}

Wenn wir für unsere Anwendung die geometrischen Objekte implementieren, können wir spezifizieren, welche Interfaces diese unterstützen. Wir sprechen davon, dass eine Klasse ein Interface implementiert. Tatsächlich wird jedoch nicht das Interface implementiert, sondern die im Interface definierten Methoden.

Im Folgenden finden Sie die Beispieldefinition einer Klasse Circle. Diese implementiert die in den Interfaces Movable und Scalable definierten Methoden.

class Circle implements Movable, Scalable {
double xPos;
double yPos;
double radius;

public void translate(double x, double y) {
this.xPos = this.xPos + x;
this.yPos = this.yPos + y;
}

public void moveToOrigin() {
this.xPos = 0;
this.yPos = 0;
}

public void scale(double scaleFactor) {
this.radius = this.radius * scaleFactor;
}
}

Wie Sie sehen, geben wir alle Interfaces, welche die Klasse implementiert nach dem Schlüsselwort implements an. In diesem Fall sind dies die Interfaces Movable und Scalable. Im Klassenrumpf müssen wir dann alle in den Interfaces definierten Methoden definieren und implementieren. Beachten Sie auch, dass wir die Methoden als public deklariert haben. Wenn wir dies nicht machen, würde Java eine Fehlermeldung ausgeben. Den genauen Grund dafür können wir erst in einer späteren Theorieeinheit besprechen.

Nicht alle geometrischen Objekte in unserer Anwendung unterstützen dieselben Operationen. So kann, zum Beispiel, das geometrische Objekt Punkt zwar im Raum verschoben werden, nicht aber skaliert werden. Entsprechend implementiert der Datentyp Point nur das Interface Movable und nicht das Interface Scalable.

class Point implements Movable {
double xPos;
double yPos;

public void translate(double x, double y) {
this.xPos = this.xPos + x;
this.yPos = this.yPos + y;
}

public void moveToOrigin() {
this.xPos = 0;
this.yPos = 0;
}

}

Die Klassen Point und Circle haben nun also beide das Interface Moveable implementiert. Davon können wir in unserer Anwendung Gebrauch machen. Wir können Methoden schreiben, welche für ein Objekt nur ein Interface voraussetzen und benutzen. Es müssen dann lediglich die in einem spezifizierten Interface definierten Methoden implementiert sein. Es wird jedoch nicht einen konkreter Datentyp verlangt.

In unserem Beispiel könnten wir eine Methode moveAround schreiben, die ein Objekt in x und y-Richtung verschiebt:

public static void moveAround(Movable m, double xv, double yv) {
m.translate(xv, yv);
}

Beachten Sie, dass wir hier statt des Datentyps Circle oder Point einfach den Namen des Interface Movable verwendet haben. Dadurch weiss Java, dass die Methode translate zur Verfügung steht.

Wir können die Methode entweder mit einem Objekt vom Datentyp Circle oder Point aufrufen.

Circle aCircle = new Circle();
Point aPoint = new Point();

moveAround(aCircle, 10, 20);
moveAround(aPoint, 0, 1);

Wir können auch direkt Variablen vom Typ des Interfaces definieren. Folgendes wäre also gültig:

Movable movable1 = new Circle();
Movable movable2 = new Point();

Probieren Sie es doch gleich selbst aus:

Experimente
  • Was passiert, wenn Sie nicht alle im Interface definierten Methoden definieren?
  • Welche Fehlermeldung erhalten Sie, wenn Sie die Methoden nicht als public deklarieren?
  • Definieren Sie auch eine Variable vom Typ Scalable. Dürfen Sie dieser eine Instanz vom Typ Point zuweisen?
  • Dürfen Sie in der Klasse Circle auch zusätzliche Methoden definieren?

Haben Sie Fragen oder Bemerkungen? Schreiben Sie diese doch ins Forum.