Eine durchdachte Modellierung einer objektorientierten Anwendung ist die Grundlage für Qualität, Erweiterbarkeit und Nachvollziehbarkeit der Kodierung. Jedes Projekt sollte demnach mit der fachlichen Modellierung der Anwendung beginnen. Im Bereich der Objektorientierung ist UML der quasi Standard.

Eine gute Modellierung sorgt vor allem auch für Sicherheit in der Verwendung durch die Entwickler und damit der Verwendung im Code. Eine abstrakte Klasse oder gar ein Interface sind beispielsweise nicht durch den new-Operator instantiierbar. Es ist also möglich allein durch geeignete Modellierung dafür zu sorgen, dass bestimmte Fehlerzustände wie das falsche instantiieren von Klassen bereits zum Zeitpunkt der Modellierung ausgeschlossen wird.

Das Anliegen und damit die Kernaussage dieses Artikels ist, dass

Basisklassen abstrakt sein sollten!

Der Konjunktiv ist hier bewusst gewählt, da es wie bei allem im Leben Ausnahmen gibt. Diese Ausnahmen kommen allerdings eher im Bereich der Framework-Modellierung oder bei Anwendungsfällen wie „Inheritance through Delegation“ (Simulierung von Mehrfachvererbung vor). Bei der zentralen Aufgabe der Objektorientierung hingegen,  die Realität, also verschiedene Objekte mit gleichen oder ähnlichen Eigenschaften zu Klassen zusammenzufassen, sind Basisklassen als abstrakt zu definieren!

Nehmen wir das folgende einfach Beispiel an, welches die realen Objekte für verschiedene Automarken, Fahrräder oder Flugzeuge in den Klassen Auto, Fahrrad und Flugzeug abbildet. Der aufmerksame Softwarearchitekt stellt nun fest, dass diese Klassen neben verschiedenen weiteren Eigenschaften auch gleichartige Eigenschaften, wie Anzahl der Räder und Herstellernamen haben. Man wird also eine geeignete Basisklasse modellieren, um Redundanzen dieser Eigenschaften zu vermeiden und diese entsprechend abstrahieren.

Das erste Resultat dieser refaktorisierten Modellierung ist die Klasse Fahrzeug welche die genannten Eigenschaften enthält. Die Klassen Auto, Fahrrad und Flugzeug erben nun von Fahrzeug.

Um die Problematik zu verdeutlichen stellt man sich die aktuelle Vererbungsmodellierung als mathematische Menge vor. Die Kindklassen Auto, Fahrrad und Flugzeug sind disjunkte (überschneidungsfreie) Teilmenge der Obermenge Fahrzeug. Die Abbildung zeigt aber auch, dass es blaue Elemente gibt, die weder der Teilmenge Auto, Fahrrad noch Flugzeug zugeordnet werden können und demnach nur in Fahrzeug spezifiziert sind. Dies ist aber sehr kritisch, denn wie kann man diese nun korrekt handhaben? Durch die Spezialisierungen Auto, Fahrrad und Flugzeug will man doch gerade erreichen, dass es nur diese Ausprägungen gibt, um diese ordentlich in der Kodierung (bspw. durch die Anwendung des Visitor-Pattern) unterscheiden zu können.

Durch die Definition der Klasse Fahrzeug als abstract erreicht man, dass die Obermenge Fahrzeug aus der Summe der disjunkten Teilmengen besteht und damit jedes Element eindeutig in einer Menge (sprich Klasse) typisiert ist.

Fazit:

Sobald Basisklassen nicht als abstract  definiert werden, besteht das Risiko Instanzen von Klassen (Objekte) erzeugen zu können, die keinem spezifizierten Typen zugeordnet werden können und somit zur Laufzeit der Anwendung zu fehlerhaften Zuständen führen können.

Anmerkung!

Wenn man nun der Meinung ist, man kommt nicht umher eine Basisklasse instantiierbar zu belassen, so sollte generell die Modellierung hinterfragt werden und ob nicht vielleicht Spezialisierung mit einem Zustand einer Klasse verwechselt wurde. Zustände von Klassen werden beispielsweise mithilfe des State-Pattern modelliert und umgesetzt.