Abstrakte Klasse
Eine abstrakte Klasse bezeichnet in der objektorientierten Programmierung eine spezielle Klasse, welche sich per Definition nicht instanziieren lässt, d. h., es lassen sich keine Objekte von ihr erzeugen, und dient somit lediglich als Strukturelement innerhalb einer Klassenhierarchie. Innerhalb von abstrakten Klassen besteht die Möglichkeit, abstrakte Methoden, also Methoden ohne Implementierung nur mit der Signatur, zu deklarieren.
Schnittstellen sind rein abstrakte Klassen, die nur Methodensignaturen deklarieren. Eine Klasse gilt dagegen bereits als abstrakt, sobald eine Methode vorhanden ist, die durch eine erbende Klasse implementiert werden muss. In einer abstrakten Klasse können auch Variablen definiert und Methoden implementiert werden.
Als Basisklassen in einer Klassenhierarchie können abstrakte Klassen grundlegende Eigenschaften ihrer abgeleiteten Klassen festlegen, ohne diese bereits konkret zu implementieren. Leitet eine Klasse von einer abstrakten Klasse ab, müssen alle vererbten abstrakten Methoden überschrieben und implementiert werden, damit die erbende Klasse selbst nicht abstrakt ist.
Abstrakte Klassen können nicht selbst instanziiert werden, nur Spezialisierungen von diesen. Dennoch können Teile des Quelltextes allgemein gehalten und nur unter Verwendung der Eigenschaften des abstrakten Basistyps implementiert werden. Durch Polymorphie kommen dabei die speziellen Implementierungen der nicht abstrakten abgeleiteten Klassen zur Ausführung.
Beispiele
[Bearbeiten | Quelltext bearbeiten ]Geometrie
[Bearbeiten | Quelltext bearbeiten ]Zweidimensionale geometrische Figuren haben gemeinsam, dass sie über einen Flächeninhalt verfügen. Je nach Figur wird dieser Flächeninhalt aber unterschiedlich berechnet.
Wird eine abstrakte Basisklasse namens Geometrisch
angelegt, kann mit einem Methodenrumpf für eine Funktion berechneFlaecheninhalt
festgelegt werden, dass alle abgeleiteten Klassen eine entsprechende Methode implementieren müssen. Zum Beispiel wird eine Klasse Rechteck
die Länge mit der Breite multiplizieren, in einer Klasse RechtwinkligesDreieck
wird die Länge mit der Höhe multipliziert und das Produkt halbiert.
Durch die Klassenhierarchie mit einer abstrakten Basisklasse hat man sich die Möglichkeit eröffnet, andernorts Funktionen zu erstellen, die ein Objekt vom Typ Geometrisch
entgegennehmen und auf ihm die Funktion berechneFlaecheninhalt
aufrufen, völlig unabhängig davon, ob es sich um Dreiecke, Rechtecke oder Kreise handelt. Die Funktionen sind somit für sämtliche geometrischen Figuren nutzbar und weisen einen hohen Grad an Flexibilität und Wiederverwendbarkeit auf.
Programmbeispiel
[Bearbeiten | Quelltext bearbeiten ]Die folgenden Beispiele sind in der Programmiersprache Java geschrieben. Als Datentyp wird eine Gleitkommazahl double verwendet.
A. Die Definition der Schnittstelle:
publicinterface Geometrisch { publicabstractdoubleberechneFlaecheninhalt(); }
B. Erstellen einer Basisklasse für Höhen- und Längenangabe:
publicabstractclass BasisFigurimplementsGeometrisch { doublelaenge; doublehoehe; // Konstruktor publicBasisFigur(finaldoubleLAENGE,finaldoubleHOEHE) { laenge=LAENGE; hoehe=HOEHE; } publicdoublegetLaenge() { returnlaenge; } publicvoidsetLaenge(finaldoubleLAENGE) { laenge=LAENGE; } publicdoublegetHoehe() { returnhoehe; } publicvoidsetHoehe(finaldoubleHOEHE) { hoehe=HOEHE; } }
C. Beispielhafte Implementierung einer konkreten Figur Rechteck:
publicclass RechteckextendsBasisFigur { // Konstruktor publicRechteck(finaldoubleLAENGE,finaldoubleHOEHE) { super(LAENGE,HOEHE); } @Override publicdoubleberechneFlaecheninhalt() { returngetLaenge()*getHoehe(); } }
D. Beispielhafte Implementierung einer weiteren konkreten Figur rechtwinkliges Dreieck:
publicclass RechtwinkligesDreieckextendsBasisFigur { // Konstruktor publicRechtwinkligesDreieck(finaldoubleLAENGE,finaldoubleHOEHE) { super(LAENGE,HOEHE); } @Override publicdoubleberechneFlaecheninhalt() { return(getLaenge()*getHoehe())/2; } }
E. Eine Beispielklasse zur erweiterten Verwendung, welche Operationen auf Basis der Schnittstelle ausführt:
publicclass GeometrischerRechner { publicstaticdoubleberechneGesamtFlaecheninhalt(finalGeometrisch[]figuren) { doubleergebnis=0; for(Geometrischfigur:figuren) { ergebnis+=figur.berechneFlaecheninhalt(); } returnergebnis; } }
F. Beispiel einer Ausführung liefert die folgende Klasse:
publicclass GeometrischesFigurenBeispiel { publicstaticvoidmain(String[]args) { // 1.1. Erstellung einzelner Objekte Geometrischrechteck=newRechteck(10,20); Geometrischdreieck=newRechtwinkligesDreieck(10,20); // 1.2. Separate Berechnung der Flächeninhalte System.out.println("Rechtecksfläche: "+rechteck.berechneFlaecheninhalt()); System.out.println("Dreiecksfläche: "+dreieck.berechneFlaecheninhalt()); // 2.1. Parameter für die Übergabe an GeometrischerRechner Geometrisch[]figuren=newGeometrisch[]{rechteck,dreieck}; // 2.2. Berechnung und Ausgabe der Gesamtfläche System.out.println("Gesamtfläche: "+GeometrischerRechner.berechneGesamtFlaecheninhalt(figuren)); } }
G. Wird dieses Programm übersetzt und ausgeführt, so erscheint in der Konsole die folgende Ausgabe:
Rechtecksfläche: 200.0 Dreiecksfläche: 100.0 Gesamtfläche: 300.0
Beispiel für den Datenbankzugriff
[Bearbeiten | Quelltext bearbeiten ]Ein klassisches Beispiel für die Anwendung abstrakter Klassen kommt aus dem Bereich der Datenbank-Anwendung. Sämtliche Methoden für den Zugriff auf die Datenbank werden in einer abstrakten Klasse definiert. Für jeden Datenbank-Typ kann eine konkrete Klasse programmiert werden, die alle geerbten Zugriffsmethoden implementiert. In der Anwendung muss an einer einzigen Stelle die konkret implementierte Klasse bekannt sein – dort wird das Objekt erzeugt. Anschließend wird es im gesamten restlichen Programmcode als Objekt vom Typ der abstrakten Klasse behandelt.
Die konkrete Klasse kann als Eigenschaft, einer sogenannten Property, in einer Datei außerhalb des Programmcodes angegeben werden. So ist kein erneutes Übersetzen nach ausgetauschter Datenbank nötig und es entsteht eine hohe Wiederverwendbarkeit der Applikation.