Wozu dient Interfaces?

matze86

Bekanntes Mitglied
Ich bin gerade an der Stelle "Interfaces" angelangt. Ich habe unten eine Interfaces Klasse und eine Klasse die Interfaces implementiert.
Mir ist soweit klar wie Interfaces arbeiten. Also man kann in Interfaces Methodenköpfe und Instanzvariablen erstellen, und in einer anderen Klasse implementieren.
Diese Klasse MUSS ja die Variablen und Methoden auch haben. Mir erschließt ehrlich gesagt nicht wozu das gut sein soll?

Man könnte ja auch auf Interfaces verzichten oder?

Hier meine beiden Klassen

Interfaces:
Java:
public interface Interface {

    public int getZahl();
    public String getWort();
}
und die Klasse die es implementiert:
Java:
public class lernen implements Interface{

    public static void main(String[] args) {
        
    }

    @Override
    public int getZahl() {
        // TODO Automatisch generierter Methodenstub
        return 0;
    }

    @Override
    public String getWort() {
        // TODO Automatisch generierter Methodenstub
        return null;
    }   
    
    
    
    
}
 
Ein Interface ist wie ein Vertrag: der Nutzer des Interfaces darf sich darauf verlassen, dass die Klasse, die das Interface implementiert, sich an die Zusicherungen hält. Der Nutzer muss also die konkrete Implementierung nicht kennen.

Beispiel:
Java:
public void show(Iterable<?> elements) {
    for (Object element : elements) {
        System.out.println(element);
    }
}

Hier erwartet die Methode ein Objekt, das das Interface Iterable anbietet. Und weil dieses Objekt dieses Interface anbietet, kann die Methode per for-each-Schleife über die Elemente iterieren.

Klar, ich könnte auch schreiben:
Java:
public void show(ArrayList<?> elements) {
    for (Object element : elements) {
        System.out.println(element);
    }
}
Nur damit ist die Methode auf ein Objekt vom Typ ArrayList beschränkt.

Interfaces dienen dazu, das Verhalten von Implementierungen zu spezifizieren, ohne eine konkrete Implementierung anzugeben. Dadurch lassen sich Abhängigkeiten im Code verringern.
 
Zunaechst werden nur Methoden deklariert in einer Schnittstelle, keine Variablen.

Und dann geht es darum unabhaengig von der konkreten Implementierung zu sein. Zwei Beispiele: Listen und Plugins.

Listen gibt es zu Hauf in der JVM, ArrayList, LinkedList und so weiter. Klassischerweise sieht das so aus:

Java:
List<String> items = new ArrayList<>();

Deklariert wird die Variable mit der Schnittstelle List, was bedeutet dass wie nur die List-Schnittstelle verwenden und von der konkreten Implementierung unabhaengig sind. Der Code kann sich zum Beispiel einfach zu

Java:
List<String> items = new LinkedList<>();

aendern lassen ohne dass es die nachfolgende Logik betrifft. Konkreter wird dies wenn die Liste von einer Methode zurueckgegeben wird:

Java:
List<String> items = repository.getItems();

Wuerde hier jetzt getItems eine ArrayList liefern und wir die Variable als solche deklarieren, koennte die Methode nie eine andere Liste zurueckliefern weil damit unser Code bricht.

Ein weiteres sehr gutes Beispiel sind Plugins. Man definiert eine Schnittstelle:

Java:
public interface Plugin {
    public abstract String doComputation(String input);
}

Und dann kann man zur Laufzeit diese Plugins verwenden ohne die konkrete Implementierung ueberhaupt irgendwann gesehen zu haben:

Java:
// Alle Plugins zur Laufzeit laden.
List<Plugin> plugins = serviceLoader.loadAllPlugins();

// Eingabe vom Benutzer holen.
String input = getInputFromUser();
// Neue Variable da wir diese konstant ueberschreiben.
String result = input;

// Ueber alle Plugins iterieren...
for (Plugin plugin : plugins) {
    // ... und diese der Reihe nach auf der Benutzereingabe aufrufen.
    result = plugin.doComputation(result);
}

// Ergebnis dem Benutzer anzeigen.
showResultToUser(result);
 
Man könnte ja auch auf Interfaces verzichten oder?
Naja...man könnte schon. Nur ist es nicht sinnvoll zu verzichten.

Als Beispiel mal eine einfache MVC-Struktur, der ungefähre Grundaufbau vieler Programme.

Dein Programm bestehe aus drei Objekten:
-Dem Model, das ist sozusagen der Datenteil deines Programms. Hier werden alle Ergebnisse dessen vorgehalten, was der Benutzer so treibt.
-Der View, das ist die Benutzeroberfläche. Die Benutzeroberfläche vom Datenteil vollständig unabhängig, und so kannst du z.B. ein älteres Programm mit Swing-Oberfläche auf JavaFX umstricken.
-Der Controller, enthält die Programmlogik.

Die drei Objekte stehen in folgender Beziehung:
Benutzer gibt irgendwelche Befehle über die View ein -> die View leitet diese Befehle an den Controller weiter -> Controller führt Befehle aus -> View liest Daten aus dem Model aus und aktualisiert sich

Um Entwicklervandalismus zu verhindern will man jetzt sicherstellen, daß z.B. die View keine Befehle direkt auf dem Model ausführen kann. Wie macht man das?

Im Model werden zwei Interfaces implementiert: Eines, daß ausschließlich harmlose Methoden für Leseoperationen enthält, und ein anderes das auch Schreibzugriffe erlaubt. Das Interface für Nur-Lesezugriff wird der View übergeben, und die View vom Model lesen jedoch keinen Schaden anrichten.
Der Controller bekommt dagegen das Interface das Schreibzugriffe unterstützt, um seiner Arbeit nachzugehen.

Und damit hast du jetzt zwar nur ein Modelobjekt, View und Controller können auf dem aber ganz unterschiedliche Dinge tun (oder eben nicht tun) und du hast eine saubere Trennung.


PS: Eine andere wichtige Einsatzmöglichkeit ist, daß du eine Bibliothek bereitstellst, die irgendwas mit völlig fremden Objekten macht. Du, der du die Bibliothek schreibst, weißt daß du einen Satz bestimmter Methoden für deine Arbeit brauchst, du kannst aber nicht wissen wie diese Methoden implementiert werden müssen. Also stellst du ein Interface bereit und sagst "Implementiere das, damit ich arbeiten kann", und dann arbeitest du auf diesem Interface.

Irgendeine Collection zum Sortieren beliebiger Objekte (SortedSet? SortedMap?) stellt z.B. ein Interface bereit, daß du implementieren mußt. Die Schreiber der Bibliothek können ja unmöglich wissen, wie und nach welchen Kriterien deine Objekte sortiert werden sollen. Also gibt es ein Interface mit einer Methode, da übergibt dir die Collection ein Objekt und du lieferst größerAls/gleich/kleinerAls zurück.
 
Zuletzt bearbeitet:
Interfaces können auch eingesetzt werden, wenn häufig(er) Änderungen oder Erweiterungen zu erwarten sind, z.B. beim Typ einer Datenstruktur , den Schichten einer MVC-Applikation oder der Zusammensetzung eines Objekts (SOLID-Prinzipien: "Composition over Inheritance")
 
Diese Klasse MUSS ja die Variablen und Methoden auch haben. Mir erschließt ehrlich gesagt nicht wozu das gut sein soll?

Man könnte ja auch auf Interfaces verzichten oder?
Wie du anhand der Posts von @M.L. , @Robert Zenz, @mihe7 und @White_Fox erkennen kannst sind Interfaces eine sehr wichtiges Sprachmittel in Java. Anders formuliert würden sie fehlen wäre das ein großer Mangel dieser Programmiersprache.
Hier noch einmal der wesentliche Unterschied zur herkömmlichen Vererbung.
Eine Basisklasse legt konkreten Code und Attribute fest, die in den Kindklassen gebraucht werden. Das hat den Vorteil das Funktionen und Attribute von den Kindklassen weiter benutzt werden können.
Der Nachteil dabei ist, dass die konkrete Implementierung den Benutzer festlegt.
Ein reines Interface verspricht nur Funktionen die Parameter bekommen und Werte zurückgeben. Wie der Benutzer den Algorithmus implementiert ist noch nicht konkret festgelegt.

Es ist zwar möglich, eine reine Schnittstelle mittels einer abstrakten Basisklasse zu formulieren.
Eine Klasse kann dann aber immer nur von einer Klasse erben.
Interface hingegen ermöglicht es der Klasse mehrere Interfaces gleichzeitig zu implementieren. Also eine Art Mehrfachvererbung.
Was die Möglichkeiten von Java erweitert. Von daher möchte ich nicht auf Interfaces verzichten.
 

Zurück
Oben