22.08.2013 Aufrufe

Grundlagen der Informatik I “Programmierung”

Grundlagen der Informatik I “Programmierung”

Grundlagen der Informatik I “Programmierung”

MEHR ANZEIGEN
WENIGER ANZEIGEN

Erfolgreiche ePaper selbst erstellen

Machen Sie aus Ihren PDF Publikationen ein blätterbares Flipbook mit unserer einzigartigen Google optimierten e-Paper Software.

jedoch dringend zu empfehlen, jegliche Seiteneffekte in Funktionen zu vermeiden, da dies schnell zu sehr<br />

unübersichtlichen Programmen führen kann und beson<strong>der</strong>s bei großen Softwaresystemen schnell zu unerwarteten<br />

Auswirkungen führen wird. 4 Will man gleichzeitig einen Wert berechnen und ein Objekt än<strong>der</strong>n, so<br />

sollte man diesen Effekt durch zwei getrennte Routinen – eine Funktion, die den Wert berechnet und eine<br />

Prozedur, die das Objekt än<strong>der</strong>t – auslösen. Es obliegt dann dem Kunden <strong>der</strong> Klasse zu entscheiden, ob er<br />

tatsächlich immer beide Operationen gemeinsam ausführen möchte.<br />

Beim Schreiben von Klassen, die Datenabstraktionen wie Fel<strong>der</strong>, Listen und Matrizen implementieren, ist es<br />

sinnvoll, Objekte nicht einfach als passive Sammlungen von Information anzusehen, son<strong>der</strong>n als “aktive Datenbehälter”<br />

mit einem internen Zustand. So wird z.B. bei Listen in <strong>der</strong> Eiffel-Bibliothek ein Cursor mitgeführt,<br />

<strong>der</strong> auf ein aktuell zu bearbeitendes Listenelement zeigt.<br />

Eine weitere Technik wird durch Vererbung möglich gemacht. Erlaubt ein bestimmter Begriff mehrere sinnvolle<br />

Implementierungen, die je nach Verwendungszweck verschieden effizient sind, dann ist es angebracht, die<br />

Schnittstelle für diesen Begriff als allgemeine Klasse zu deklarieren, und die verschiedenen Implementierungen<br />

in verschiedenen Erbenklassen, die allesamt nur die in <strong>der</strong> Ahnenklasse genannte features exportieren. Meist<br />

ist die allgemeine Klasse eine aufgeschobene Klasse – Beispiele findet man hierzu in <strong>der</strong> Eiffel-Bibliothek zuhauf<br />

– manchmal aber stellt sie auch eine Standardimplementierung <strong>der</strong> vielfältig benötigten Routinen bereit, die<br />

nur in manchen Spezialfällen verän<strong>der</strong>t wird.<br />

Umgekehrt kann man aber auch mehrere Schnittstellen für ein und denselben Begriff anbieten, was durch<br />

die Kombination von Vererbung und Re-Export geerbter features ermöglicht wird. Diese Technik ist sinnvoll,<br />

wenn verschiedenen Kunden verschiedene Sichten auf dasselbe Objekt geboten werden sollen, wie dies z.B. im<br />

Falle <strong>der</strong> Bankkonten (vgl. Seite 99) <strong>der</strong> Fall war.<br />

Eine tiefergehende Diskussion von Klassenschnittstellen findet man in [Meyer, 1988, Kapitel 9]. Hier werden<br />

die obengenannten Prinzipien anhand einiger Beispiele ausführlich erläutert.<br />

4.1.5 Vererbungstechniken<br />

Vererbung ist einer <strong>der</strong> entscheidenden Vorteile des objektorientierten Entwurfs und sollte daher gezielt,<br />

aber richtig eingesetzt werden. Wie bereits in Abschnitt 3.8.11 besprochen, bestimmt vor allem die logische<br />

Beziehung zwischen zwei Klassen, ob besser geerbt o<strong>der</strong> benutzt werden soll. Vererbung sollte genau dann<br />

genutzt werden, wenn Objekte einer Klasse Spezialfälle einer an<strong>der</strong>en Klasse sind. In allen an<strong>der</strong>en Fällen ist<br />

ein Benutzen sinnvoller. Gründe, von dieser Vorgehensweise abzuweichen, haben wir bereits besprochen.<br />

Im allgemeinen wird man eine neu zu definiernde Klasse als Spezialfall (also Erben) einer bereits existierenden<br />

Klasse beschreiben können. Zuweilen steht man aber vor <strong>der</strong> Situation, daß die existierenden Klassen<br />

nicht allgemein genug sind, und man eine Verallgemeinerung erzeugen muß (wie z.B. bei den geometrischen<br />

Objekten, die man erst erfunden hatte, nachdem es schon Punkte, Geraden, Dreiecke und Kreise gab). Bisher<br />

gibt es keine Programmiersprache, die hierzu einen generellen Mechanismus, also ein Gegenstück zur inherit-<br />

Klausel, anbietet. Verallgemeinerungen müssen von Hand durch Editieren des Spezialfalls generiert werden.<br />

Außerdem ist es bei Verallgemeinerungen ausnahmsweise nötig, Eingriffe in eine bereits existierende Klasse<br />

vorzunehmen: in <strong>der</strong> spezielleren Klasse muß eine entsprechende Erbklausel mit Redefinitionsvereinbarungen<br />

ergänzt werden. Diese Än<strong>der</strong>ungen sind jedoch geringfügig und haben keine Effekte auf weitere Klassen.<br />

Redefinition ist eine <strong>der</strong> wichtigsten Techniken bei Vererbung. Sie sollte immer dann eingesetzt werden, wenn<br />

für den Spezialfall <strong>der</strong> Erben eine effizientere Implementierung als die <strong>der</strong> Elternklasse gefunden werden kann.<br />

Ein beson<strong>der</strong>er Fall ist dabei die Redefinition von Funktionen als Attribute. Dies kostet zwar Speicherplatz,<br />

spart aber zuweilen sehr viel Rechenzeit. Der Einsatz dieses Mittels erfor<strong>der</strong>t aber ein sorgfältiges Abwägen.<br />

Bei Redefinition ist immer zu beachten, daß die Semantik <strong>der</strong> redefinierten Routine erhalten bleiben muß.<br />

In Abschnitt 3.8.10 haben wir Mechanismen kennengelernt, die sicherstellen, daß sowohl die Vor- und Nach-<br />

4 Eine legitime Ausnahme von dieser Richtlinie wird in [Meyer, 1988, Kapitel 7.7] besprochen.

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!