Abstraktion ist eines der vier Grundprinzipien der objektorientierten Programmierung (neben Kapselung, Vererbung und Polymorphismus). Sie ermöglicht es, gemeinsame Eigenschaften und Verhaltensweisen in übergeordneten Klassen oder Schnittstellen zu definieren, ohne eine konkrete Implementierung vorzugeben. Dadurch können verschiedene Unterklassen die gleiche Schnittstelle nutzen, aber unterschiedliches Verhalten zeigen.
Eine abstrakte Klasse ist eine Klasse, die nicht direkt instanziiert werden kann. Sie dient als Basisklasse (Oberklasse) und kann sowohl abstrakte Methoden (ohne Implementierung) als auch konkrete Methoden (mit Implementierung) enthalten.
// Java-Beispiel
abstract class Fahrzeug {
protected String marke;
public Fahrzeug(String marke) {
this.marke = marke;
}
// Abstrakte Methode - MUSS überschrieben werden
abstract void beschleunigen();
// Konkrete Methode - KANN überschrieben werden
public String getMarke() {
return this.marke;
}
}
class Auto extends Fahrzeug {
public Auto(String marke) {
super(marke);
}
@Override
void beschleunigen() {
System.out.println(marke + " beschleunigt mit Motor.");
}
}
class Fahrrad extends Fahrzeug {
public Fahrrad(String marke) {
super(marke);
}
@Override
void beschleunigen() {
System.out.println(marke + ": Fahrer tritt in die Pedale.");
}
}Merkmale abstrakter Klassen: Sie können Instanzvariablen, Konstruktoren, konkrete und abstrakte Methoden besitzen. Eine Unterklasse muss alle abstrakten Methoden implementieren, sofern sie selbst nicht abstrakt ist.
Ein Interface definiert einen Vertrag: Es legt fest, welche Methoden eine Klasse bereitstellen muss, aber nicht wie. Seit Java 8 können Interfaces auch Default-Methoden mit Implementierung enthalten.
// Java-Beispiel
interface Fahrbar {
void fahren(); // abstrakt (implizit)
void bremsen(); // abstrakt
// Default-Methode (seit Java 8)
default void hupen() {
System.out.println("Huuup!");
}
}
interface Elektrisch {
void laden();
}
// Eine Klasse kann MEHRERE Interfaces implementieren
class Elektroauto extends Fahrzeug implements Fahrbar, Elektrisch {
public Elektroauto(String marke) {
super(marke);
}
@Override void beschleunigen() { /* ... */ }
@Override public void fahren() { /* ... */ }
@Override public void bremsen() { /* ... */ }
@Override public void laden() { /* ... */ }
}Polymorphismus (Vielgestaltigkeit) ermöglicht, dass eine Variable vom Typ der Oberklasse oder des Interfaces auf Objekte verschiedener Unterklassen verweisen kann. Zur Laufzeit wird die richtige Methode aufgerufen (dynamische Bindung):
Fahrzeug[] fuhrpark = {
new Auto("BMW"),
new Fahrrad("Canyon"),
new Elektroauto("Tesla")
};
for (Fahrzeug f : fuhrpark) {
f.beschleunigen(); // Ruft jeweils die spezifische Methode auf
}Der Compiler kennt nur den statischen Typ (Fahrzeug), aber zur Laufzeit wird die Methode des dynamischen Typs (Auto, Fahrrad, Elektroauto) ausgeführt.
Design Patterns (Entwurfsmuster) sind bewährte Lösungsschablonen für wiederkehrende Probleme im Software-Design. Abstrakte Klassen und Interfaces spielen dabei eine zentrale Rolle:
Sortierer.Datenexport mit der Template-Methode exportiere().Beobachter wird von allen Klassen implementiert, die auf Änderungen reagieren wollen.Abitur-Tipp: Im Abitur wird häufig verlangt, UML-Klassendiagramme zu lesen und zu erstellen, die abstrakte Klassen (kursiver Name) und Interfaces («interface») enthalten. Präge dir die Unterschiede ein: abstrakte Klasse = „ist-ein“-Beziehung mit geteiltem Code; Interface = „kann“-Fähigkeit mit Mehrfachvererbung. Typische Aufgabe: Modelliere eine Hierarchie und begründe, warum du abstrakte Klasse oder Interface gewählt hast.