Interface (OOP)
Ein Interface ist in der objektorientierten Programmierung ein Vertrag, der festlegt, welche Methoden eine Klasse implementieren muss, ohne eine konkrete Implementierung vorzugeben.
Auf dieser Seite
- Grundprinzip von Interfaces
- Unterschied zu abstrakten Klassen
- Interfaces in verschiedenen Programmiersprachen
- Mehrfachimplementierung
- Interface Segregation Principle
- Polymorphismus durch Interfaces
- Praktische Anwendungsfälle
- Vorteile von Interfaces
- Interfaces in der IT-Ausbildung
- Quellen und weiterführende Links
Ein Interface (deutsch: Schnittstelle) ist in der objektorientierten Programmierung (OOP) ein Vertrag, der festlegt, welche Methoden eine Klasse implementieren muss. Im Gegensatz zu einer Klasse enthält ein Interface keine konkrete Implementierung. Es definiert nur die Signaturen der Methoden. Jede Klasse, die ein Interface implementiert, verpflichtet sich, alle im Interface definierten Methoden bereitzustellen.
Du kannst dir ein Interface wie einen Arbeitsvertrag vorstellen: Der Vertrag legt fest, welche Aufgaben erledigt werden müssen (die Methodensignaturen), aber nicht, wie genau sie erledigt werden (die Implementierung). Verschiedene Mitarbeiter (Klassen) können denselben Vertrag (Interface) erfüllen, aber ihre Arbeit auf unterschiedliche Weise erledigen.
Grundprinzip von Interfaces
Das Grundprinzip eines Interfaces basiert auf der Trennung von Spezifikation und Implementierung. Ein Interface beschreibt, was eine Klasse können muss, nicht wie sie es tun soll. Diese Abstraktion ermöglicht es, Code zu schreiben, der mit verschiedenen Implementierungen arbeiten kann, ohne deren Details zu kennen.
// Interface definiert den Vertrag
public interface Zahlungsmethode {
boolean bezahlen(double betrag);
String getName();
}
// Klasse implementiert das Interface
public class Kreditkarte implements Zahlungsmethode {
@Override
public boolean bezahlen(double betrag) {
// Konkrete Implementierung für Kreditkartenzahlung
System.out.println("Zahle " + betrag + " EUR per Kreditkarte");
return true;
}
@Override
public String getName() {
return "Kreditkarte";
}
}
// Weitere Implementierung desselben Interfaces
public class PayPal implements Zahlungsmethode {
@Override
public boolean bezahlen(double betrag) {
System.out.println("Zahle " + betrag + " EUR über PayPal");
return true;
}
@Override
public String getName() {
return "PayPal";
}
}
Im Beispiel definiert das Interface Zahlungsmethode zwei Methoden. Sowohl Kreditkarte als auch PayPal implementieren dieses Interface, aber auf unterschiedliche Weise. Code, der mit dem Interface arbeitet, kann beide Klassen austauschbar verwenden.
Unterschied zu abstrakten Klassen
Interfaces und abstrakte Klassen haben Ähnlichkeiten, unterscheiden sich aber in wichtigen Punkten. Die Wahl zwischen beiden beeinflusst das Design deiner Software erheblich.
| Aspekt | Interface | Abstrakte Klasse |
|---|---|---|
| Implementierung | Keine (nur Signaturen)* | Kann konkrete Methoden enthalten |
| Mehrfachvererbung | Klasse kann mehrere Interfaces implementieren | Klasse kann nur von einer Klasse erben |
| Konstruktor | Nicht möglich | Kann Konstruktoren haben |
| Felder/Attribute | Nur Konstanten (public static final) | Kann Instanzvariablen haben |
| Beziehungstyp | ”kann-tun”-Beziehung | ”ist-ein”-Beziehung |
| Verwendung | Gemeinsames Verhalten für nicht verwandte Klassen | Gemeinsame Basis für verwandte Klassen |
*Seit Java 8 können Interfaces auch Default-Methoden mit Implementierung enthalten.
Verwende ein Interface, wenn verschiedene, nicht verwandte Klassen ein gemeinsames Verhalten teilen sollen. Verwende eine abstrakte Klasse, wenn du eine gemeinsame Basis für eng verwandte Klassen mit geteiltem Code schaffen willst.
Interfaces in verschiedenen Programmiersprachen
Die Umsetzung von Interfaces variiert zwischen Programmiersprachen. Während das Grundkonzept gleich bleibt, gibt es wichtige Unterschiede in Syntax und Möglichkeiten.
Java
In Java sind Interfaces Referenztypen, ähnlich wie Klassen. Seit Java 8 können Interfaces auch Default-Methoden mit konkreter Implementierung enthalten, was die Erweiterung bestehender Interfaces ermöglicht, ohne alle implementierenden Klassen zu brechen.
public interface Fahrzeug {
void starten();
void stoppen();
// Default-Methode (seit Java 8)
default void hupen() {
System.out.println("Huuup!");
}
}
C#
In C# beginnen Interface-Namen per Konvention mit einem “I” (z.B. IComparable, IDisposable). C# unterstützt sowohl implizite als auch explizite Interface-Implementierung und seit C# 8.0 auch Default-Interface-Methoden.
public interface IFahrzeug
{
void Starten();
void Stoppen();
}
public class Auto : IFahrzeug
{
public void Starten() => Console.WriteLine("Motor startet");
public void Stoppen() => Console.WriteLine("Motor stoppt");
}
TypeScript
TypeScript verwendet strukturelles Tippen (Structural Typing). Das bedeutet, dass ein Objekt ein Interface automatisch erfüllt, wenn es alle erforderlichen Eigenschaften und Methoden hat. Ohne explizite Deklaration.
interface Fahrzeug {
marke: string;
starten(): void;
}
// Explizite Implementierung
class Auto implements Fahrzeug {
marke: string;
starten() { console.log("Auto startet"); }
}
// Strukturelle Kompatibilität - auch ohne "implements"
const fahrrad = {
marke: "Canyon",
starten() { console.log("Los geht's!"); }
};
// fahrrad erfüllt das Fahrzeug-Interface strukturell
function fahren(f: Fahrzeug) {
f.starten();
}
fahren(fahrrad); // Funktioniert!
Go
Go geht noch einen Schritt weiter als TypeScript: Interfaces werden implizit erfüllt. Es gibt kein implements-Schlüsselwort. Ein Typ erfüllt ein Interface automatisch, wenn er alle Methoden des Interfaces implementiert.
type Fahrzeug interface {
Starten()
Stoppen()
}
type Auto struct {
Marke string
}
// Auto implementiert Fahrzeug implizit
func (a Auto) Starten() {
fmt.Println("Auto startet")
}
func (a Auto) Stoppen() {
fmt.Println("Auto stoppt")
}
Mehrfachimplementierung
Ein großer Vorteil von Interfaces ist die Möglichkeit der Mehrfachimplementierung. Während eine Klasse in den meisten Sprachen nur von einer einzigen Klasse erben kann (Einfachvererbung), kann sie beliebig viele Interfaces implementieren.
public interface Schwimmfaehig {
void schwimmen();
}
public interface Flugfaehig {
void fliegen();
}
// Ente implementiert beide Interfaces
public class Ente implements Schwimmfaehig, Flugfaehig {
@Override
public void schwimmen() {
System.out.println("Ente schwimmt auf dem Teich");
}
@Override
public void fliegen() {
System.out.println("Ente fliegt durch die Luft");
}
}
Diese Flexibilität ermöglicht es, Verhaltensweisen zu kombinieren, ohne komplexe Vererbungshierarchien zu schaffen. Die Ente “ist” sowohl schwimmfähig als auch flugfähig, ohne dass diese Fähigkeiten durch Vererbung vorgegeben werden müssen.
Interface Segregation Principle
Das Interface Segregation Principle (ISP) ist eines der fünf SOLID-Prinzipien und wurde von Robert C. Martin formuliert. Es besagt: “Kein Client sollte gezwungen sein, von Methoden abzuhängen, die er nicht verwendet.”
In der Praxis bedeutet das: Kleine, fokussierte Interfaces sind besser als große, allgemeine. Statt ein “fettes” Interface mit vielen Methoden zu definieren, solltest du mehrere kleine, spezialisierte Interfaces erstellen.
// SCHLECHT: Fettes Interface
public interface Drucker {
void drucken();
void scannen();
void faxen();
void kopieren();
}
// Ein einfacher Drucker müsste alle Methoden implementieren,
// auch wenn er nicht scannen oder faxen kann.
// GUT: Segregierte Interfaces
public interface Druckbar {
void drucken();
}
public interface Scannbar {
void scannen();
}
public interface Faxbar {
void faxen();
}
// Einfacher Drucker implementiert nur was er kann
public class EinfacherDrucker implements Druckbar {
@Override
public void drucken() {
System.out.println("Drucke Dokument...");
}
}
// Multifunktionsgerät implementiert alle benötigten Interfaces
public class Multifunktionsgeraet implements Druckbar, Scannbar, Faxbar {
@Override
public void drucken() { /* ... */ }
@Override
public void scannen() { /* ... */ }
@Override
public void faxen() { /* ... */ }
}
Polymorphismus durch Interfaces
Interfaces ermöglichen Polymorphismus: die Fähigkeit, verschiedene Objekte über dieselbe Schnittstelle anzusprechen. Code, der gegen ein Interface programmiert ist, kann mit jeder Klasse arbeiten, die dieses Interface implementiert.
public class Zahlungsabwicklung {
// Methode akzeptiert jede Zahlungsmethode
public void verarbeiteZahlung(Zahlungsmethode methode, double betrag) {
System.out.println("Verarbeite Zahlung über " + methode.getName());
boolean erfolg = methode.bezahlen(betrag);
if (erfolg) {
System.out.println("Zahlung erfolgreich!");
}
}
}
// Verwendung
Zahlungsabwicklung abwicklung = new Zahlungsabwicklung();
abwicklung.verarbeiteZahlung(new Kreditkarte(), 99.99);
abwicklung.verarbeiteZahlung(new PayPal(), 49.99);
abwicklung.verarbeiteZahlung(new Ueberweisung(), 199.99);
Die Methode verarbeiteZahlung kennt nur das Interface Zahlungsmethode. Sie funktioniert mit jeder Klasse, die dieses Interface implementiert. Das macht den Code erweiterbar, ohne bestehende Teile ändern zu müssen (Open-Closed Principle).
Praktische Anwendungsfälle
Interfaces sind in vielen Designmustern und Architekturkonzepten zentral. Hier einige typische Anwendungsfälle:
- Repository Pattern: Ein Interface definiert Datenzugriffsoperationen. Verschiedene Implementierungen können Datenbanken, APIs oder Mock-Daten für Tests nutzen.
- Strategy Pattern: Verschiedene Algorithmen implementieren dasselbe Interface und können zur Laufzeit ausgetauscht werden.
- Dependency Injection: Klassen hängen von Interfaces ab, nicht von konkreten Implementierungen. Das erleichtert Testing und macht den Code flexibler.
- Plugin-Systeme: Plugins implementieren ein vordefiniertes Interface und können dynamisch geladen werden.
- Adapter Pattern: Ein Adapter implementiert ein erwartetes Interface und delegiert an eine inkompatible Klasse.
Vorteile von Interfaces
Die Verwendung von Interfaces bietet zahlreiche Vorteile für die Softwareentwicklung:
- Lose Kopplung: Code hängt von Abstraktionen ab, nicht von konkreten Implementierungen. Das reduziert Abhängigkeiten zwischen Modulen.
- Testbarkeit: Für Tests können Mock-Implementierungen eines Interfaces erstellt werden, ohne echte Datenbanken oder externe Dienste zu benötigen.
- Austauschbarkeit: Implementierungen können ausgetauscht werden, ohne den aufrufenden Code zu ändern.
- Klare Verträge: Interfaces dokumentieren explizit, welche Methoden verfügbar sind und was von Implementierungen erwartet wird.
- Teamarbeit: Teams können parallel arbeiten. Eine Gruppe definiert Interfaces, andere implementieren sie.
Interfaces in der IT-Ausbildung
Das Verständnis von Interfaces ist ein zentraler Bestandteil der Ausbildung zum Fachinformatiker für Anwendungsentwicklung. In der IHK-Prüfung werden häufig Fragen zu OOP-Konzepten gestellt, darunter auch Interfaces.
In der Praxis wirst du Interfaces bei der Entwicklung von Webanwendungen, APIs und bei der Arbeit mit Frameworks wie Spring Boot (Java), ASP.NET Core (C#) oder Angular (TypeScript) regelmäßig begegnen. Das Dependency-Injection-Pattern, das in diesen Frameworks zentral ist, basiert auf Interfaces.
Auch als Fachinformatiker für Systemintegration begegnest du dem Interface-Konzept. Wenn auch eher auf Systemebene bei der Integration verschiedener Softwarekomponenten und bei der Arbeit mit APIs.
Quellen und weiterführende Links
- Oracle Java Tutorials: Interfaces – Offizielle Java-Dokumentation zu Interfaces
- Microsoft Learn: Interfaces in C# – C#-spezifische Interface-Dokumentation
- TypeScript Handbook: Interfaces – TypeScript-Dokumentation
- Go Tour: Interfaces – Einführung in Go-Interfaces
- Stackify: Interface Segregation Principle – Ausführlicher Artikel zum ISP
Prüfungsbezug
Passt zu deiner Prüfungsvorbereitung
Wenn dir dieser Begriff in Aufgaben, Projektdokumentation oder Fachgespräch begegnet, ordne ihn direkt in den Prüfungsstoff ein.