Ich hatte erst kürzlich einen Beitrag über objektorientierte Programmierung in Java geschrieben. Diesen findest du hier. Da der Beitrag eh schon recht lang geworden war, wollte ich das Thema Interfaces und abstrakte Klassen und dessen Unterschiede in einem separaten Beitrag noch einmal aufgreifen, denn sie gehören zu den wichtigsten Konzepten der objektorientierten Programmierung.
Beide dienen dazu, eine gemeinsame Basis für mehrere Klassen bereitzustellen, aber sie haben unterschiedliche Anwendungsfälle und Einschränkungen. In diesem Beitrag erkläre ich die Unterschiede anhand eines einfachen Beispiels und erläutere, wann welche Technik sinnvoll eingesetzt wird.
Eine abstrakte Klasse ist eine Klasse, die nicht direkt instanziiert werden kann, also nicht über einen Konstruktor erzeugt werden. Sie kann abstrakte Methoden (Methoden ohne Implementierung, also ohne Methodenbody) sowie konkrete Methoden (Methoden mit Implementierung, also mit Methodenbody) enthalten. Abstrakte Klassen eignen sich besonders dann, wenn eine gemeinsame Basisimplementierung für mehrere verwandte Klassen benötigt wird.
Beispiel:
Hier haben wir eine abstrakte Klasse Fahrzeug, die eine konkrete Methode anzeigen() und eine abstrakte Methode fahren() definiert.
abstract class Fahrzeug {
protected String name;
public Fahrzeug(String name) {
this.name = name;
}
public abstract void fahren(); // abstrakte Methode
public void anzeigen() {
System.out.println("Fahrzeug: " + name);
}
}
Ein Interface definiert eine Sammlung von Methoden, die von einer Klasse implementiert werden müssen. Alle Methoden in einem Interface sind standardmäßig public und abstract (außer default- oder static-Methoden, die eine Implementierung haben können). Interfaces sind ideal, wenn Klassen eine gemeinsame Schnittstelle teilen sollen, aber keine gemeinsame Implementierung erben.
Beispiel:
Hier wird das Interface Motorisiert definiert, das zwei Methoden enthält, die von jeder implementierenden Klasse bereitgestellt werden müssen.
interface Motorisiert {
void starten();
void stoppen();
}
Jetzt erstellen wir zwei konkrete Klassen, die sowohl die abstrakte Klasse Fahrzeug erweitern als auch das Interface Motorisiert implementieren.
class Auto extends Fahrzeug implements Motorisiert {
public Auto(String name) {
super(name);
}
@Override
public void fahren() {
System.out.println(name + " fährt auf der Straße.");
}
@Override
public void starten() {
System.out.println(name + " Motor gestartet.");
}
@Override
public void stoppen() {
System.out.println(name + " Motor gestoppt.");
}
}
class Boot extends Fahrzeug implements Motorisiert {
public Boot(String name) {
super(name);
}
@Override
public void fahren() {
System.out.println(name + " fährt auf dem Wasser.");
}
@Override
public void starten() {
System.out.println(name + " Motor gestartet.");
}
@Override
public void stoppen() {
System.out.println(name + " Motor gestoppt.");
}
}
Hier erben Auto und Boot von Fahrzeug und implementieren gleichzeitig das Interface Motorisiert. Dadurch profitieren sie von der gemeinsamen Basis der abstrakten Klasse und der Flexibilität des Interfaces.
Eine abstrakte Klasse sollte verwendet werden, wenn eine gemeinsame Implementierung für mehrere Klassen benötigt wird, die Klassen eine enge Beziehung zueinander haben (z.B. verschiedene Arten von Fahrzeugen) oder Konstruktoren und Attribute in der Basisklasse definiert werden sollen.
Ein Interface sollte verwendet werden, wenn eine Klasse Funktionalitäten von mehreren Quellen benötigt (da keine Mehrfachvererbung in Java möglich ist), es um reine Schnittstellen ohne gemeinsame Implementierung geht oder wenn verschiedene Klassen eine gemeinsame Schnittstelle haben sollen, aber nicht zwingend verwandt sein müssen.
Sowohl abstrakte Klassen als auch Interfaces haben also ihre Daseinsberechtigung. Während man abstrakte Klassen für eine gemeinsame Basisimplementierung nutzen sollte, eignen sich Interfaces besser, um lose gekoppelte Strukturen zu definieren. Oft ergibt sich eine optimale Lösung durch die Kombination beider Konzepte – genau wie im Beispiel mit den Klassen Fahrzeug und Motorisiert.
Ich hoffe, dieser Beitrag hat dir geholfen, die Unterschiede zwischen abstrakten Klassen und Interfaces anhand der Beispiele besser zu verstehen. Welche Erfahrungen hast mit abstrakten Klassen und Interfaces gemacht? Schreibt es gerne in die Kommentare!
