EMZETT.
Login

Abstraction

Kurz: Nur das “Was” nach außen zeigen, nicht das “Wie” — eine Klasse oder Schnittstelle definiert, welche Operationen möglich sind, ohne deren konkrete Umsetzung preiszugeben.

Genauer: Java setzt Abstraktion über zwei Mechanismen um: abstract class (kann sowohl fertige als auch offene, noch zu implementierende Methoden enthalten, aber selbst nicht direkt instanziiert werden) und Interface (reine Vertragsdefinition ohne eigenen Zustand). Beide zwingen Unterklassen, die offenen Methoden konkret zu implementieren.

Im Detail

Die Kernidee: Vertrag statt Umsetzung

Abstraktion ist eines der vier Grundprinzipien der OOP (neben Kapselung, Vererbung und Polymorphie) und beantwortet die Frage: “Was muss der Nutzer einer Klasse wissen, um sie zu benutzen?” — nicht mehr als nötig. Eine List z. B. verspricht “füge Elemente hinzu, hol sie per Index ab”, egal ob dahinter eine ArrayList (Array-basiert, schneller wahlfreier Zugriff) oder LinkedList (verkettete Knoten, schnelleres Einfügen in der Mitte) steckt. Der aufrufende Code muss die interne Implementierung nicht kennen und kann sie austauschen, ohne selbst geändert zu werden — man deklariert Variablen deshalb typischerweise als List<T> liste = new ArrayList<>(); statt ArrayList<T> liste = new ArrayList<>();, um genau diese Austauschbarkeit im eigenen Code zu erhalten.

abstract class: gemeinsamer Code plus offene Punkte

abstract class eignet sich, wenn Unterklassen gemeinsamen Code teilen sollen (z. B. eine Basisimplementierung), aber trotzdem einzelne Methoden erzwingen wollen:

abstract class Form {
    abstract double flaeche(); // muss implementiert werden - kein Methodenrumpf
 
    void beschreibe() { // gemeinsamer, fertiger Code - für ALLE Unterklassen gleich
        System.out.println("Fläche: " + flaeche());
    }
}
 
class Kreis extends Form {
    double radius;
    Kreis(double radius) { this.radius = radius; }
 
    @Override
    double flaeche() { return Math.PI * radius * radius; }
}
 
class Rechteck extends Form {
    double breite, hoehe;
    Rechteck(double breite, double hoehe) { this.breite = breite; this.hoehe = hoehe; }
 
    @Override
    double flaeche() { return breite * hoehe; }
}

Eine abstrakte Klasse kann NICHT direkt instanziiert werden (new Form() kompiliert nicht) — sie existiert nur, um von konkreten Unterklassen erweitert zu werden. Enthält eine Klasse auch nur EINE abstrakte Methode, muss die ganze Klasse selbst als abstract markiert werden, auch wenn sie sonst nur fertigen Code enthält.

interface: reiner Vertrag über Klassenhierarchien hinweg

Ein Interface dagegen definiert traditionell nur den Vertrag, ganz ohne eigenen Zustand (Felder — abgesehen von static final-Konstanten) und ohne Implementierung. Seit Java 8 sind allerdings auch default-Methoden mit Standardimplementierung erlaubt, was die Grenze zur abstrakten Klasse etwas verwischt:

interface Fliegend {
    void fliege();
 
    default void lande() { // Standardimplementierung, überschreibbar
        System.out.println("Landung eingeleitet");
    }
}
 
interface Schwimmend {
    void schwimme();
}
 
// Eine Klasse kann beliebig viele Interfaces implementieren
class Ente implements Fliegend, Schwimmend {
    public void fliege() { System.out.println("Ente fliegt"); }
    public void schwimme() { System.out.println("Ente schwimmt"); }
}

Faustregel für die Wahl

abstract class für eine “ist-ein”-Beziehung mit gemeinsamem Zustand und gemeinsamer Basislogik (z. B. Form → Kreis, Rechteck), interface für ein “kann-X” quer über unabhängige Klassenhierarchien hinweg — eine Ente kann gleichzeitig Fliegend und Schwimmend sein, obwohl beide Fähigkeiten fachlich nichts miteinander zu tun haben. Der entscheidende technische Unterschied: Eine Klasse kann beliebig viele Interfaces implementieren, aber nur von GENAU EINER Klasse erben (Java kennt keine Mehrfachvererbung von Klassen, um die sogenannte “Diamond-Problem”-Mehrdeutigkeit zu vermeiden, die C++ mit seiner Mehrfachvererbung lösen muss).

Abgrenzung zu Encapsulation

Abstraction wird oft mit Encapsulation verwechselt, weil beide irgendwie mit “Verstecken” zu tun haben — der Unterschied: Abstraction versteckt Komplexität auf Design-Ebene (welche Methoden gibt es, nicht wie sie implementiert sind), Encapsulation versteckt konkreten Zustand auf Implementierungsebene (private-Felder mit Gettern/Settern). Eine Klasse kann perfekt gekapselt (alle Felder private) und trotzdem schlecht abstrahiert sein (zu viele, zu spezifische öffentliche Methoden, die interne Details preisgeben).

Siehe auch: Interface, OOP, Encapsulation, Polymorphism, Classes