Jetzt anmelden...

Login
Passwort
Registrieren

Java Tutorial #36

Was ist ein Interface in Java?

In Java ist die Mehrfachvererbung nicht erlaubt. Doch aus dieser scheinbaren Schwäche gewinnt unsere Lieblingsprogrammiersprache eine ihrer größten Stärken. Mit Interfaces nämlich umschiffen wir die Regel der Einfachvererbung elegant und erkunden neue Möglichkeiten, hoch flexiblen Code zu schreiben.

Kommentare [0]

Stefan 11.07.2019

Infos zum Artikel

Kategorie Java
Autor Stefan
Datum 11.07.2019

Thema in Kurzform

  • Eine Java-Klasse kann von maximal einer Klasse erben, aber beliebig viele Interfaces implementieren.
  • Das Interface ist ein Typ, der aus abstrakten Methoden und Konstanten besteht.
interface MeinInterface {

    int konstante = 10;  // = public static final
    void methode();  // = public abstract

}
class meineKlasse implements MeinInterface {

    // Methoden müssen implementiert werden

}

Wozu braucht man Interfaces?

Das Problem

Wissen Sie, was ein Cyborg ist? Laut Wikipedia bezeichnet der Begriff Mischwesen aus lebendigem Organismus und Maschine.

Übertragen wir die Beziehung zwischen Mensch, Maschine und Cyborg in die Objektorientierung, könnte sich folgende Klassenhierarchie ergeben:

Java Interface

Die Klasse Cyborg braucht Eigenschaften und Methoden von Mensch und von Maschine und würde daher gleichzeitig von Mensch und Maschine erben. Doch da gibt es ein Problem:

  • Mehrfachvererbung ist in Java nicht erlaubt!

Könnte Java (wie etwa C++) Mehrfachvererbung, würde das unsere Programme unnötig verkomplizieren: Stellen Sie sich einfach mal vor, dass sowohl Mensch als auch Maschine eine Methode namens laufen() haben. Wenn nun Cyborg von beiden Klassen die Methode erben würde, hätten wir ein fettes Dilemma, da es völlig unklar wäre, welche laufen()-Methode auf einem Cyborg-Objekt ausgeführt werden sollte.

Da eine Java-Klasse also nur von maximal einer anderen Klasse erben kann, bleibt die Frage weiter offen, wie wir unseren Cyborg hinbekommen.

Die Lösung: Interfaces!

Mit Interfaces (Schnittstellen) lösen wir in Java das Problem der Einfachvererbung und ermöglichen, dass eine Klasse auf mehrere Typen zurückgeht. Eine Klasse kann neben der Oberklasse auf eine beliebige Anzahl an Interfaces zurückgehen - wir sagen dann, das eine Klasse ein Interface implementiert.

Java Interface

Die Klasse Cyborg erweitert die Klasse Mensch und implementiert das Interface Maschine.

Eine Oberklasse zu erweitern und ein Interface zu implementieren sind zwei unterschiedliche Vorgänge. Dies kommt auch in unterschiedlichen Schlüsselwörtern (extends und implements) zum Ausdruck:

public class Cyborg extends Mensch implements Maschine{
    //
}

Wenn eine Klasse sowohl erbt als auch ein Interface implementiert, muss extends immer vor implements stehen.

Mehrere implementierte Interfaces werden im Klassenkopf kommasepariert geschrieben.

Der Aufbau eines Interfaces

Interfaces sind keine Klassen, ähneln diesen aber im Aufbau. Der folgende Code zeigt den Interface-Typ Maschine:

interface Maschine {

    void ladeBatterie();
    void toolsTesten();
    boolean funktionsfaehig();

}

Anhand von Maschine können wir die verpflichtenden Eigenschaften eines Interface schon erkennen:

  • Die Zugriffsstufe eines Interfaces ist immer public. Deshalb kann der Zugriffsmodifikator weggelassen werden.
  • Anstatt des Schlüsselworts class wird interface verwendet.
  • Es gibt keinen Konstruktor (Interfaces sind keine Klassen, also werden sie auch nicht instanziiert).
  • Alle Methoden in einem Interface sind abstrakt. Es darf keine einzige konkrete Methoden geben. Deshalb ist das Schlüsselwort abstract nicht nötig.
  • Die Interface-Methoden sind automatisch öffentlich sichtbar. Es darf keine andere Zugriffsstufe gewählt werden. Darum muss das Schlüsselwort public nicht explizit aufgeführt werden.

Wir müssen uns merken: Der fehlende Access-Modifier meint nicht, dass die Methoden default-Zugriff hätten, sondern dass sie "automatisch" public sind.

Ein Interface ist wie eine 100%-ige abstrakte Klasse. Wenn eine Klasse nicht alle Methoden der Interfaces implementiert (d.h. Methodenkörper liefert), so erbt sie damit abstrakte Methoden. Die Klasse muss dann wiederum selbst als abstract gekennzeichnet werden.

In unserem Fall heißt das: Entweder die Klasse Cyborg macht durch Implementierung alle drei Methoden ladeBatterie(), toolsTesten() und funktionsfaehig() konkret oder sie muss selbst als abstrakt deklariert werden.

Variablen in Interfaces

Da von Interfaces keine Instanzen (Objekte) erzeugt werden können, gibt es auch keine Instanzvariablen.

Konstanten allerdings sind kein Problem. Zum Beispiel:

public static final double maxEnergie = 100.0;

Da in Interfaces ausschließlich öffentliche Konstanten-Variablen erlaubt sind, müssen die Schlüsselwörter public, static und final nicht explizit genannt werden (auch wenn es natürlich trotzdem möglich ist). Der Compiler ergänzt die fehlenden Angaben für uns.

Ergänzen wir unser Interface Maschine nun um die Konstante maxEnergie:

interface Maschine {

    double maxEnergie = 100.0; // = public static final

    void ladeBatterie();
    void toolsTesten();
    boolean funktionsfaehig();

}

Interfaces und Polymorphie

Interfaces sind super, um in Java doch noch eine Art Mehrfachvererbung hinzubekommen. Aber Sie haben noch einen zweiten großen Vorteil.

Wenn unsere Klassen ein Interface implementieren, spielen sie eine "Rolle" und es ist dabei völlig schnuppe, aus welchem Vererbungsbaum sie kommen:

Java Interface

Cyborg und Cyberdog haben keine gemeinsame Vererbungsstruktur. Da sie aber das Interface Maschine implementieren, können sie beide die Rolle Maschine spielen: Sowohl der Cyborg (Mensch) als auch der Cyberdog (Hund) sind Maschinen.

Diese Tatsache hat einen riesigen Nutzen: Da ein Interface - genau wie eine Klasse - einen Typ definiert, können wir Referenzvariablen oder Sammlungen von einem Interface-Typ deklarieren. Damit können wir die Prinzipien der Polymorphie nach allen Regeln der Kunst voll ausreizen und unseren Code unwiderstehlich machen.

Hier ein Beispiel:

ArrayList<Maschine> maschinen = new ArrayList<>();
maschinen.add(new Cyborg());
maschinen.add(new Cyberdog());
maschinen.add(new Waschmaschine());

Wir erstellen eine ArrayList, die alle Typen aufnehmen kann, die das Interface Maschine implementieren. Anschließend packen wir drei passende neue anonyme Objekte rein.

Cyborg, Cyberdog und jetzt sogar Waschmaschine entstammen ganz unterschiedlichen Vererbungsstrukturen. Aber sie haben alle neben ihres vererbten Typs zusätzlich den Interface-Typ Maschine. Mit anderen Worten: Es sind Maschinen; und das ist ihre Gemeinsamkeit.

Übungen

einfach

Betrachten Sie das folgende Interface und die Klasse:

public interface Flyable {

    public void fly(){
        //
    }

}
public class Animal implements Flyable {

    @Override
    public void fly(){
        //
    }
}

Ist der Code gültig?

Lösung ein-/ausblenden

mittel

Zugegeben: Für eine mittlere Aufgabe relativ tricky, denn es ist eine kleine Gemeinheit eingebaut.

Der folgende Code erzeugt einen Compiler-Fehler - warum?

public interface Inter1 {
    void action();
}
public interface Inter2 {
    void action();
}
public class MeineKlasse implements Inter1, Inter2 {

    @Override
    void action(){

    }
}

A. Inter1 und Inter2 haben die selbe Methode action(). In MeineKlasse ist es unklar, welche ausgeführt werden soll.
B. Ein Interface hat nur abstrakte Methoden: Dies muss durch das Schlüsselwort abstract kenntlich gemacht werden.
C. Man kann nicht mehrere Interfaces implementieren.
D. Die Zugriffsstufe der überschriebenen Methode ist falsch.

Lösung ein-/ausblenden

schwer

Folgender Code ist gegeben:

interface X1{ }
interface X2{ }
class A { }
class B extends A implements X1{ }
class C extends B implements X2{
   D d = new D();
}
class D { }

Welche der folgenden Aussagen ist korrekt (3 richtige):

A. D ist ein B
B. B hat ein D
C. C ist ein A
D. C ist ein X1
E. C ist ein X2

Lösung ein-/ausblenden

Kommentar schreiben

Nur angemeldete und aktivierte Benutzer können kommentieren.

Alle Kommentare

Es gibt bislang noch keine Kommentare zu diesem Thema.

Verzweigungen in Java

Eine zentrale Notwendigkeit der Programmierung sind Verzweigungen.

Konstruktoren bei Vererbung

Trainieren Sie ihre Konstruktoren-Skills

Java Variablen erklärt

Wie werden Variablen eingesetzt? Was bedeutet Deklarieren und Initialisieren?

FALCONBYTE.NET

Handmade with 🖤️

© 2018, 2019 Stefan E. Heller

Impressum | Datenschutz

facebook programmieren lernen twitter programmieren lernen youtube programmieren lernen