Java Tutorial #30

Abtrakte Klassen und Methoden in Java

2021-03-20 | credit: ©Jacob Lund/ stock.adobe

Thema in Kurzform

Von abstrakten Klassen können keine Objekte erzeugt werden.

Abstrakte Methoden haben keinen Rumpf und dürfen nur in abstrakten Klassen vorkommen. Sie müssen in einer Unterklasse überschrieben und implementiert werden.

Abstrakte Klassen

Um den Sinn hinter dem Konzept der abstrakten Klassen zu verstehen, schauen wir uns zunächst einmal folgende einfache Vererbungshierarchie an:

Java abstrakte Klassen

Es ist naheliegend, dass wir von den Klassen FalkeElefant und Eisbaer Objekte erzeugen. Wie sinnvoll ist es aber, die allgemeine Klasse Tier zu instantiieren? Wie können uns ganz konkret einen Falken, einen Elefanten oder einen Eisbären vorstellen. Aber ein allgemeines "Tier"? Wohl eher nicht. 

Tatsächlich ist es so, dass die Klasse Tier viel zu unspezifisch ist, als dass wir davon Objekte erzeugen sollten. Denn wir wollen keine Tier-Objekte, sondern Falke-, Elefant- und Eisbaer-Objekte! 

Das heißt natürlich nicht, dass die Klasse Tier unwichtig wäre. Ganz im Gegenteil: Sie ist absolut essentiell für unsere Vererbungslogik und Programmstruktur, zumal sie als Superklasse für andere Klassen dient. 

Das Schlüsselwort abstract

Tier ist etwas Abstraktes, von dem es keine Objekte geben sollte. Um zu verhindern, dass eine Klasse wie Tier jemals instantiiert wird, müssen wir sie als abstract markieren:

public abstract class Tier {

    //

}

Setzen wir also das Schlüsselwort abstract direkt hinter den Zugriffsmodifikator, haben wir die Klasse als abstrakte Klasse markiert, von der niemals(!) ein Objekt erstellt werden kann. Versuchen wir es dennoch, erhalten wir einen Compiler-Fehler.

Tier t = new Tier(); // nein!

Der Compiler meldet: 'Tier' is abstract; cannot be instantiated. Genau so muss das sein 😀 

Konkrete Klassen

Klassen, die nicht abstrakt sind, nennt man konkrete Klassen. Davon können Objekte erzeugt werden. 

Wenn wir in unseren Programmen die Vererbungsstruktur anlegen, sollten wir genau überlegen, welche Klassen abstrakt und welche konkret sind. Konkrete Klassen sollten so spezifisch wie möglich sein, dass die Objekterzeugung sinnvoll erscheint. 

Erweitern wir unsere Vererbungshierarchie von oben nun ein wenig, um das Zusammenspiel von abstrakten und konkreten Klassen zu sehen.

Java abstrakte Klassen

Die Klasse Falke war zuerst noch eine konkrete Klasse. Da wir sie aber hier um zwei Unterklassen erweitert haben (Sakerfalke und Turmfalke) sind diese beiden spezifischer, d.h. konkreter, als Falke. Deshalb sollten wir Falke als abstractmarkieren und die Objekterzeugung von dieser Klasse verbieten. Falke ist damit eine abstrakte Unterklasse. Dasselbe Prinzip gilt auch bei den Klassen BaerGrizzly und EisbaerElefant wird nicht erweitert, auch wenn das natürlich ohne Weiteres denkbar wäre.

Abstrakte Methoden

Neben Klassen können auch Methoden als abstrakt markiert werden:

public abstract class Tier {

    public abstract void bewegen();

}

In der abstrakten Klasse Tier haben wir eine abstrakte Methode bewegen() definiert. Dabei wird Schlüsselwort abstract direkt hinter den Zugriffsmodifikator gesetzt. Fällt Ihnen hier aber noch etwas anderes auf? 

Richtig: Es fehlen die beiden geschweiften Methoden-Klammern { } und die Methode hat keinen Rumpf. Daraus ergeben sich folgende Regeln für abstrakte Methoden: 

  • Da abstrakte Methoden keinen Rumpf haben, können sie nicht ausgeführtwerden. 
  • Abstrakte Methoden dürfen ausschließlich in abstrakten Klassen vorkommen (bei der ersten abstrakten Methode muss die Klasse ebenfalls mit abstractmarkiert werden). Oder anders ausgedrückt: In einer konkreten Klasse darf es keine abstrakten Methoden geben. 
  • Abstrakte Methoden müssen in einer Unterklasse überschrieben und implementiert werden (d.h. einen Methoden-Körper programmieren). 

Würden wir abstrakte Methoden in konkreten Klassen zulassen, hieße das, dass wir Objekte mit nicht implementierten Methoden erzeugen könnten. Was für eine grausame Vorstellung 😨

Der Sinn von abstrakten Methoden

Beim Entwickeln von objektorientierten Programmen wissen wir schon im oberen Bereich des Vererbungsbaums, dass wir bestimmte Methoden für konkrete Unterklassen brauchen werden. Allerdings wäre es noch zu früh und die Oberklasse ist zu unspezifisch, um die konkrete Funktionsweise dieser Methoden für alle Unterklassen jetzt schon festzulegen. Diese Arbeit wird eine geeignete Unterklasse erledigen.

Denken Sie doch mal an die abstrakte Klasse Tier. Wir wissen, dass ein Tier sich bewegen kann (darum hat die Klasse auch eine Methode bewegen()). Allerdings ist Tier noch viel zu allgemein und vage, als dass wir wüssten, wie diese Bewegung genau sein soll. Es ist unmöglich, dass sich alle Tierarten gleich bewegen! Ein Falke etwa bewegt sich vollkommen anders als ein Elefant oder Bär. Eben deshalb hat die Methode zu diesem Zeitpunkt noch keinen Code und ist abstrakt. 

Wie gesagt muss garantiert sein, dass eine abstrakte Methode von einer der Unterklassen implementiert und damit konkret wird. So können wir bewegen() etwa in der Klasse Elefant überschreiben und implementieren:

@Override
public void bewegen(){
    System.out.println("Ich bewege mich schwer und oft langsam");
}

Elefant ist eine konkrete Klasse, da sie die von Tier geerbte abstrakte Methode bewegen() implementiert, selbst keine abstrakte Methode hat sowie nicht als abstrakte Klasse markiert wurde. 

Wie sieht es nun aber mit Falke aus? In unserer Grafik oben ist die Klasse als abstract gekennzeichnet. Dies kann drei Ursachen haben: 

  • Die Methode bewegen() ist in dieser Klasse Falke nicht implementiert (sondern erst in den Unterklassen Sakerfalke und Turmfalkeoder
  • bewegen() ist zwar implementiert, aber die Klasse definiert mindestens eine neue abstrakte Methode oder
  • bewegen() ist zwar implementiert und es gibt auch keine neuen abstrakten Methoden, doch Falke ist als abstrakte Klasse markiert.

Das Gleiche gilt natürlich auch für abstrakte Klasse Baer

Soviel zu den abstrakten Klassen und Methoden. Wir hoffen, wir konnten das Thema etwas klarer machen. 

Werbung

Java lernen

Werde zum Java Profi!

PHP Lernen

Lerne serverbasierte Programmierung

JavaScript lernen

Skille dein Webcoding

FALCONBYTE.NET

Handmade with 🖤️

© 2018-2023 Stefan E. Heller

Impressum | Datenschutz | Changelog

Falconbyte Youtube Falconbyte GitHub facebook programmieren lernen twitter programmieren lernen discord programmieren lernen