Menu

Abstrakte Klassen in Java: das Schlüsselwort abstract erklärt

Was eine abstrakte Klasse in Java ist, wie man abstrakte Methoden deklariert, warum man sie nicht instanziieren kann und wann man eine abstrakte Klasse statt eines Interface wählt.

Diese Seite enthält ausführbare Editoren - bearbeiten, ausführen und Ausgabe sofort sehen.

Was eine abstrakte Klasse ist

Ein Interface deklariert Verhalten ohne Zustand. Eine gewöhnliche Klasse ist vollständig implementiert und lässt sich instanziieren. Eine abstrakte Klasse steht zwischen beiden: Sie kann wie eine normale Klasse Felder, Konstruktoren und fertige Methoden tragen, kann aber auch einige Methoden unimplementiert lassen und verbietet die direkte Instanziierung. Du markierst sie mit dem Schlüsselwort abstract.

Die Idee besteht darin, alles, was Unterklassen gemeinsam haben, an einer Stelle zu bündeln und zugleich jede Unterklasse zu zwingen, die Teile auszufüllen, die sich wirklich unterscheiden.

Animal definiert getName() einmalig für jede Unterklasse und deklariert sound() als abstract - eine Methode mit Signatur, aber ohne Rumpf, die Dog liefern muss.

Du kannst eine abstrakte Klasse nicht instanziieren

Da eine abstrakte Klasse unfertige Methoden haben kann, würdest du beim direkten Erzeugen ein unvollständiges Objekt erhalten. Der Compiler lehnt das ab:

Animal a = new Animal("???");   // error: Animal is abstract; cannot be instantiated

Du instanziierst immer eine konkrete Unterklasse - eine, die jede abstrakte Methode implementiert hat. Diese Instanz der Unterklasse kann dann in einer Variablen des abstrakten Typs gehalten werden, und genau so nutzt man die Abstraktion.

Abstrakte Methoden zwingen Unterklassen zur Entscheidung

Eine abstract-Methode ist ein Versprechen, das die Unterklasse einhalten muss. Vergisst eine Unterklasse, eine davon zu implementieren, wird die Unterklasse selbst abstrakt und der Compiler weist dich darauf hin. Das ist der wichtigste Hebel der abstrakten Klasse: Sie garantiert, dass bestimmtes Verhalten existiert, ohne vorzuschreiben, was es tut.

describe() wird nur einmal in Shape geschrieben und ruft dennoch das eigene area() jeder Unterklasse auf. Die abstrakte Klasse liefert das gemeinsame Gerüst; die Unterklassen liefern die Details.

Gemeinsamer Zustand und Konstruktoren

Anders als ein traditionelles Interface kann eine abstrakte Klasse Instanzfelder halten und Konstruktoren definieren. Der Konstruktor erzeugt nie für sich allein ein Animal oder Shape - er läuft über super(...), wenn eine Unterklasse erzeugt wird, und initialisiert dabei den gemeinsamen Zustand.

Das Feld balance, deposit und applyInterest leben an einer einzigen Stelle. Nur die Regel, die tatsächlich variiert - interestRate() -, bleibt abstrakt. Der Konstruktor einer Unterklasse muss super(...) aufrufen, um diesen geerbten Zustand zu initialisieren.

Eine Falle: abstract und final mischen

abstract und final sind Gegensätze. Eine abstract-Methode verlangt eine Überschreibung; eine final-Methode verbietet sie. Dieselbe Sache auf beide Weisen zu markieren - oder eine abstrakte Klasse final zu machen - ist ein Kompilierfehler. Bedenke außerdem, dass eine abstrakte Klasse null abstrakte Methoden haben kann: eine Klasse nur deshalb als abstract zu deklarieren, um ihre Instanziierung zu verhindern, ist erlaubt und manchmal nützlich für Basistypen, die du nur erweitern möchtest.

abstract final class Bad { }        // error: abstract and final conflict

abstract class Base {
    abstract final void f();        // error: an abstract method can't be final
}

Abstrakte Klasse versus Interface

Sie überschneiden sich, daher hängt die Wahl davon ab, was du teilen musst:

  • Abstrakte Klasse - verwende sie für eng verwandte Klassen, die Zustand und Code teilen. Sowohl Savings als auch Checking erweitern Account und erben das Feld balance sowie die deposit-Logik. Eine Klasse erweitert nur eine einzige.
  • Interface - verwende es für eine Fähigkeit, die nicht verwandte Klassen teilen können. Ein Bird und ein Airplane können beide Flyable sein, ohne irgendeine Implementierung zu teilen. Eine Klasse kann mehrere implementieren.

Ein häufiges Muster kombiniert beides: Ein Interface definiert den Vertrag, und eine abstrakte Klasse implementiert den Boilerplate-Code, sodass konkrete Unterklassen nur das ausfüllen, was einzigartig ist.

Als Nächstes: Polymorphie

Beachte, dass wir in jedem obigen Beispiel eine Instanz der Unterklasse in einer Variablen des abstrakten Typs gehalten, dann eine Methode aufgerufen und automatisch das Verhalten der Unterklasse erhalten haben. Genau diese eine Fähigkeit - ein Referenztyp, viele Laufzeitverhalten - ist die Polymorphie, und sie ist es, die abstrakte Klassen und Interfaces auszahlen lässt. Das ist das Thema der nächsten Seite.

Häufig gestellte Fragen

Was ist eine abstrakte Klasse in Java?

Eine abstrakte Klasse ist eine mit dem Schlüsselwort abstract deklarierte Klasse, die sich nicht eigenständig instanziieren lässt. Sie ist dafür gedacht, erweitert zu werden. Sie kann vollständig implementierte Methoden und Felder (gemeinsamer Zustand und Code für Unterklassen) mit abstract-Methoden ohne Rumpf mischen - diese liegen in der Verantwortung jeder Unterklasse, sie zu implementieren.

Kann man eine abstrakte Klasse in Java instanziieren?

Nein. new AbstractType() ist ein Kompilierfehler, weil eine abstrakte Klasse nicht implementierte (abstract) Methoden haben kann, sodass das Objekt unvollständig wäre. Man instanziiert eine konkrete Unterklasse, die alle abstrakten Methoden ausfüllt, und speichert sie dann in einer Variablen des abstrakten Typs.

Was ist der Unterschied zwischen einer abstrakten Klasse und einem Interface in Java?

Eine abstrakte Klasse kann Instanzfelder, Konstruktoren und teilweise implementierte Logik besitzen, aber eine Klasse kann nur eine einzige erweitern. Ein Interface deklariert Verhalten ohne Instanzzustand, und eine Klasse kann mehrere implementieren. Verwende eine abstrakte Klasse, um Zustand und Code zwischen eng verwandten Unterklassen zu teilen; verwende ein Interface, um nicht verwandten Klassen eine gemeinsame Fähigkeit zu geben.

Coddy programming languages illustration

Lerne mit Coddy zu programmieren

LOS GEHT'S