2 Objektorientierter Programmierstil (OOPS)
2.1 theoretisches Konzept der OO-Entwicklung
Die OO-Entwicklung abstrahiert Objekte aus der Praxis und modelliert sie
möglichst real in der zugrundeliegenden Programmiersprache. Ein OO-System
besteht so aus abgegrenzten Objekten, deren Klassen und deren Beziehungen
untereinander. Dieses Konzept wird deshalb als so vielversprechend angesehen,
weil auf diese Weise eine möglichst natürliche und wirklichkeitsnahe
Modellierung des praktischen Problems entsteht. Viele Befürworter
der OO-Programmierung (OOP) versuchen, dies mit der Behauptung zu
untermauern, Datendefinitionen eines Programms seien beständiger und
stabiler als dessen Funktionalität, weswegen es nützlicher sei,
mehr nach Daten zu gruppieren. Ob sich aber die Grundfunktionalität
wesentlich mehr ändern sollte als die Hauptdaten, ist zumindest umstritten.
Denn daß wenigstens Datentypen konstant bleiben stimmt nicht mehr
für generische Programmierung, wie sie mit der Standard Template Library
(STL9,10) möglich ist. Generisch
programmieren heißt dabei genaugenommen, daß man Teile eines
spezifischen Programms frei verändern kann, um es flexibel an Designänderungen
anzupassen. Dabei können solche Änderungen an einer leicht zugänglichen
Stelle konfiguriert werden, ohne den Rest des Programms ändern zu
müssen. Ohne solche Möglichkeiten müßte sonst quasi
jeder einzelne Befehl, der den veränderten Abschnitt verwendet umgeschrieben
werden. Heute wird generische Programmierung allerdings hauptsächlich
mit dem bekanntesten Softwaremodul dieser Kategorie, der STL assoziiert.
Dieses Modul besteht aus einer vollständigen Kollektion von Funktionen
und Klassen zur Datenverarbeitung. Es ist so entworfen, daß zu verwaltende
Daten und die Algorithmen, die sie verwenden, nur über eine generisch
veränderbare Kopplung verbunden sind. Auf diese Weise können
mit der Änderung einer einzigen Anweisung ganze Programmteile an neue
Anforderungen angepaßt werden. Die Algorithmen bleiben gleich, egal
ob die benötigten Daten gesammelt im Speicher vorliegen oder als bunte
Menge von Dateien auf dem Computer. Viele Vorteile generischer Programmierung
können jedoch schon allein mit der OOP genutzt werden. Die wesentlichen
vorteilhaften Aspekte bei der OOP sind dabei:
Anmerkung: Im folgenden wird unter einem (abstrakten) Modul ein
Programmteil oder eine zusammengesetzte Einheit eines Programms verstanden.
Ein Modul könnte somit sowohl ein echtes Softwaremodul als auch ein
einzelnes Objekt oder eine Funktion sein.
-
Modularität:
-
Funktional oder logisch zusammengehörige Teile eines Programms werden
besser zusammen gruppiert und können von anderen Modulen als Einheit
verwendet werden. Der innere Zusammenhalt eines Moduls wird Kohäsion
genannt, wobei ein sinnvolles Modul sich durch eine große Kohäsion
auszeichnet.
-

-
Man würde zum Beispiel Funktionen, die mathematische Berechnungen
durchführen, alle in einer Bibliothek unterbringen, aber alle trigonometrischen
Funktionen mit deren Daten innerhalb der Bibliothek in ein anderes Modul
verpacken als die Routinen zur Integralrechnung.
-
Abstraktion:
-
Bei Objekten wird auf das Wesentliche fokussiert, unwichtige Details
dagegen ignoriert, um größere intellektuelle Einheiten verarbeiten
zu können und die hohe Komplexität auch breiterer Systeme noch
beherrschen zu können6.
-
Verkapselung:
-
Verkapselung zwingt dazu Module abstrakt zu betrachten, weil diese Informationen
verbergen. Der große Vorteil hiervon ist, daß ein Programmierer
eines einzelnen Moduls nach außen, zu anderen Modulen nur einen Teil
der Funktion freilegt und alles andere extern für nicht benutzbar
(private) erklärt. Dies erzwingt, daß bei Veränderungen
der privaten Teile eines Moduls andere Module nicht auch noch angepaßt
werden müssen. Nur noch der geringe öffentlich (public)
von anderen Modulen verwendbare Teil, der oft als Interface bezeichnet
wird, muß unverändert erhalten bleiben. Die Summe der eigenen
Schnittstelle und aller im Modul benutzten, fremden Schnittstellen heißt
Kopplung, sie ist der äußere Zusammenhalt zwischen Modulen.
Ein sinnvolles Modul zeichnet sich hierbei durch eine kleine Kopplung
zu anderen Modulen aus.
-
Vererbung:
-
Objekte können Eigenschaften (Datenattribute) und Verhalten
(Operationen) von übergeordneten, allgemeineren Objekten übernehmen,
und nur speziellere Daten und Funktionen hinzufügen. So können
auf eine simple Weise Programmteile wiederverwendet werden. Dies
beschreibt das Faktum: "ein Unterobjekt erbt von einem Basisobjekt,
die Unterklasse ist von einer Basisklasse abgeleitet."
-

-
Man kann also eine Objektart "Tier" erstellen, die Daten wie Alter
und Operationen wie Verstecken besitzt. Dann gäbe es zwei
Unterklassen "Pfau" und "Katze", die beide von der Klasse "Tier" abgeleitet
sind und so die allgemeinen Daten wie Alter erben, also gemeinsam haben
(auch wenn sie unterschiedliche Werte für Alter haben, haben sie doch
alle ein Attribut Alter). Aber Pfaue unterscheiden sich von Katzen, also
enthalten sie Eigenschaften, die über die Basis "Tier" hinaus gehen.
Ein Pfau hat beispielsweise die zusätzliche Eigenschaft Flügellänge
und die neue Operation fliegen, die für Katzen einfach keinen
Sinn machen würden. Vererbung führt also dazu, daß die
Gemeinsamkeiten mehrerer ähnlicher Objekte nur einmal erstellt werden
müssen. Wenn eine Operation nicht unterscheiden muß, ob sie
mit einer Katze oder einem Pfau arbeitet, wenn also beispielsweise eine
Liste aller Käfiginsassen eines Zoos erstellt werden soll, dann wird
sie mit Objekten des Basistyps "Tier" arbeiten und nicht getrennt für
Katzen und Pfauen.
Vererbung ist einer der größten Vorteile der OOP, der es
ermöglicht, mehrfach verwendete (Teil-) Algorithmen und Strukturen
nur einmal zu programmieren. Auf diese Weise muß sozusagen das Rad
nicht jedesmal wieder neu erfunden werden, weil häufig schon gelöste
Teilprobleme aus anderen Projekten oder anderen Modulen übernommen
werden können12. Bei einem umsichtigen Design
kann so Funktionalität schon im voraus unabhängig vom zu realisieren
Projekt implementiert werden.
-
Polymorphie:
-
Eine Operation, die in einer Basisklasse definiert ist, und für eine
abgeleitete Klasse dynamisch abgeändert oder überschrieben
werden kann, heißt polymorph oder auch virtuell.
-

-
So könnte man eine Funktion frißt zur Klasse "Tier"
erstellen, die die täglich benötigte Futtermenge berechnet. Ist
die Menge, die ein Pfau frißt aber ganz anders zu berechnen als bei
dem Rest der Tiere, so kann die Funktion frißt bei der Objektart
"Pfau" überschrieben und mit einem anderen Algorithmus belegt sein.
Von außen kann aber trotzdem einfach in einer Menge von Objekten
des Tiertyps die Operation frißt angewandt werden, ohne
noch unterscheiden zu müssen, ob es sich bei dem jeweiligen Tier um
einen Pfau handelt oder nicht.
2.2 Objekte als Spiegelbild der Natur
Reale Sachverhalte mit der OO-Terminologie zu beschreiben basiert selber
auf einem theoretischen Modell, welches davon ausgeht, daß sich alle
zur Modellbildung relevanten Sachverhalte eines bestimmten Problems vollständig
mit Hilfe der OO-Begriffe beschreiben läßt. Daß diese
Modellvorstellung der OOP tatsächlich geeignet ist, mit ihren Elementen
ein Problem zu beschreiben, wird in den nächsten Abschnitten deutlich.
Dabei soll auch durch die Vergleiche mit der Realität ein etwas natürlicheres
Verständnis der OO-Elemente erreicht werden. Mit einem konkreten Verständnis
der praktischen Entsprechungen ist es möglich die OO-Elemente auf
eine ausreichend intuitive Weise handhaben zu können. Ob das Modell
der OOP dagegen auch brauchbar ist, wird am Ende der Arbeit sicherstehen,
wenn in einem zweiten Schritt das Praxisprojekt erfolgreich realisiert
werden konnte.
2.2.1 Entsprechungen der Modellbegriffe
Objekt und Klasse:
Das OO-Modell macht intensiven Gebrauch der kategorisierenden Begriffe
Objekt und Klasse. Im theoretischen Fundament wird strikt zwischen ihnen
unterschieden, so, daß einzelne Sachverhalte jeweils aufgeteilt werden
in entweder Objekt oder Klasse. Diese strenge Trennung ist aber nur im
Ansatz und zur Definition nötig. Um die wichtigsten Eigenschaften
von Objekten und Klassen untersuchen zu können, sind beide als strukturell
gleich ansehbar. Sowohl die Felder und Beziehungen einer Klasse als auch
die ihrer Objekte können gleichwertig betrachtet werden. Um diese
Theorie zum OO-Modell hinreichend zu erklären, ist ein kleiner Ausflug
in die Philosophie erforderlich:
Sowohl der Begriff eines Objekts als auch der einer Klasse ist in der
Theorie als künstliche, formale Beschreibung eines bestimmten Sachverhalts
der Realität gedacht. Der Unterschied zwischen einer Klasse und ihren
Objekten besteht schließlich, philosophisch gesehen, nur darin, daß
eine Klasse eine Form im Allgemeinen und ein Objekt einen Inhalt
im Allgemeinen widerspiegelt. Beide, Form und Inhalt machen nur Sinn, wenn
sie in ihrer dialektischen Synthese als Ganzes gesehen werden. Eine
Ansammlung von Werten allein sagt nichts aus, und eine bloße Formatvorlage
beinhaltet natürlich auch keine Information. Erst die Form deklariert,
wie ein vorliegendes Datum zu deuten ist, und erst der Inhalt definiert
konkrete Informationen, die tatsächlich benutzt werden können.
So sind auch alle Objekte, die allein auf einem Computer existieren nur
unbestimmte Inhalte (denn sie sind intern immer nur eine Folge von in Bytes
angeordneten Zahlen). Damit ein Computerprogramm nun weiß, was es
mit solch formlosen Inhalten anfangen soll, wird zu jedem Objekt auf unterschiedliche
Weisen eine Information assoziiert, die dessen Klasse bestimmt. Diese Klasse
wiederum kann auf einem Computer ausschließlich in Form von
Daten, also Inhalt, vorliegen, die ebensowenig deutbar sind ohne Form.
Selbst, wenn einer Klasseninformation diese Form von der Programmiersprache
gegeben wird, ist doch auch das Übersetzungsprogramm der Programmiersprache
selbst nur ein Inhalt auf seinem Speichermedium. Damit dieser Inhalt nun
wieder durch eine geeignete Form interpretiert und benutzt wird, deutet
die Hardware eines Computers solche Programme als ausführbare Befehlssequenz.
Also ist ein Objekt dasselbe wie eine Klasse? Nein. Aber Objekte und Klassen
haben erst beide zusammengenommen Eigenschaften und sinnvolle Beziehungen
zu anderen Objekten und Klassen. Da für eine Deutung, wie auch für
eine Modellierung nur das dialektische Paar Objekt und Klasse Sinn ergibt,
wird im folgenden einfach nur noch von einem Objekt gesprochen, von dem
angenommen wird, daß seine zugehörige Form, die Klasse bekannt
ist. Nur bei besonderen Differenzen zwischen Klasse und Objekt wird explizit
beides aufgeführt.
Für die Praxis der Informatik können wir festhalten, daß
ein Objekt immer mit seiner Klassenvorlage, die deutbar sei, assoziiert
werden kann. Dieser Mechanismus, die Klassen eines Objekts ermitteln zu
können wird in der Informatik angeblich erstmals mit den neuartigen
Runtime Type Informations (RTTI) angewandt. Doch die theoretische
Informatik sollte hier vermitteln können, daß es sich bei RTTI
nur um eine lange vernachlässigte Eigenschaft der OOP handelt.
2.2.2 Ein Objekt aus der Sicht seines physischen
Äquivalent's (einer Sache):
Der formalisierte Begriff eines Objekts der Informatik, das ein reales
Objekt modelliert, ist leichter zu verstehen, wenn für die abstrakten
Feldelemente eines Objekts physische Entsprechungen genannt werden:
Anmerkung: Ein Objekt als Sache wird in der Informatik
auch zur Modellierung von Personen gebraucht.
-
Die Attribute eines Objekts repräsentieren die Eigenschaften einer
Sache:
Beispielsweise
ist ein bestimmtes Objekt, eine Blaumeise, uu der Klasse der Vögel
gehörend, 10cm groß und hat eine überwiegend blaue Farbe.
Dann würde ein Modell der Informatik hierzu die Fakten erklären,
daß ein Objekt der Klasse Vogel mit dem Namen "Blaumeise"
das Attribut Größe,
mit dem Wert 0.1m und ein Attribut Farbe
mit dem Wert blau aufweist.
-
Attribute können den Status eines Objekts beinhalten:
Eine
Blaumeise kann unterschiedliche Zustände der Sättigung einnehmen,
auch die Fluggeschwindigkeit wäre strenggenommen ein Zustand. So würde
ein Objekt "Blaumeise" sein Zustandsattribut Hunger
auf groß, mittel und satt einstellen
können. Und sein Attribut Fluggeschwindigkeit kann
auf schnell, bummeln oder null
gesetzt werden.
-
Operationen eines Objekts spiegeln die Aktionen wieder, die andere Objekte
auf dieses wirken lassen können:
So kann
man eine Blaumeise etwas fressen lassen oder sie anlocken. Dazu würde
ein Systemanalytiker für die Blaumeise die Operationen frißt
und anlocken aufstellen. Die Operation frißt
müßte dann den Sättigungszustand über das Attribut
Hunger abhängig von der eingenommenen Futtermenge
aktualisieren. Die Operation anlocken müßte
je nach Laune der Meise abschätzen, ob sich die Blaumeise anlocken
läßt oder nicht.
Wie man sieht, sind zu einem Objekt gegebene Probleme mit solchen Metaphern
recht leicht auf die Ebene der Computer in OO-Elemente zu modellieren,
und damit zeigt sich das Design für die Problemlösung als sehr
einfach:
"Metaphern
haben unschätzbare Vorteile. Ihr Verhalten ist vorhersehbar und jedermann
verständlich. Unnötige Erklärungen und Mißverständnisse
fallen weg. Fakten lassen sich schneller erlernen und lehren. Metaphern
trennen Wesentliches von Unwesentlichem und führen so zu abstrakten
Konzepten, die ein Denken auf höherer Ebene ermöglichen und Fehler
auf niedrigerer Ebene vermeiden." - Fernando J. Corbató