Grundlagen der Informatik I “Programmierung”
Grundlagen der Informatik I “Programmierung” Grundlagen der Informatik I “Programmierung”
Definition 3.8.5 (Konformität) Ein Datentyp B ist genau dann konform zu einem Datentyp A (“B conforms to A”), wenn eine der folgenden Bedingungen erfüllt ist. 1. A und B sind identisch, 2. A ist von der Form expanded B oder B ist von der Form expanded A, 3. A ist REAL oder DOUBLE und B ist INTEGER oder REAL, 4. A ist eine Klasse ohne generische Parameter und B ist eine Klasse, die A in der inherit-Klausel aufführt, 5. A ist von der Form G[A1, ..An] und B führt G[B1, ..Bn] in der inherit-Klausel auf, wobei G eine generische Klasse ist und jedes der Bi zu Ai konform ist, 6. B ist von der Form like anchor und der Typ von anchor ist konform zu A, 7. Es gibt einen Typen C mit der Eigenschaft, daß B konform ist zu C und C konform zu A. Eine ausführliche Diskussion von Konformität und weitere Verfeinerungen der Definition findet man in [Meyer, 1992, Kapitel 13]. Vererbung und Redefinition begünstigen einen Softwareentwicklungsstil, der sich vollkommen von den bisher üblichen Vorgehensweisen unterscheidet. Statt jedes Problem ganz von Neuem zu lösen, kann man auf Lösungen ähnlicher Probleme aufbauen, ihre Dienstleistungen erweitern und gegebenenfalls durch Redefinition für die spezielle Fragestellung optimieren. Diese Form der Wiederverwendung bestehender Softwaremodule ist hochgradig ökonomisch und bescheiden zugleich: sie erkennt die Leistungen anderer Softwareentwickler an, anstatt sie durch eine völlige Neuentwicklung zu ignorieren. Die Notwendigkeit, hierfür die Gemeinsamkeiten zwischen Gruppen verwandter Daten zu berücksichtigen, findet ebenfalls eine Antwort: in Netzwerken von Klassen, die durch Vererbung miteinander verbunden sind, können wir die logischen Beziehungen zwischen diesen Gruppen ausdrücken. Wiederverwendbarkeit wird dadurch gefördert, daß die Deklaration eines features soweit wie möglich nach oben verschoben wird, damit dieses feature in einer großen Anzahl von Nachkommen zur Verfügung steht. 3.8.4 Polymorphismus Wir haben gesehen, daß durch Vererbung die Wiederverwendbarkeit von Softwaremodulen erheblich gesteigert werden kann. Darüber hinaus hat Vererbung aber noch einen weiteren wichtigen Aspekt, nämlich Polymorphismus. Dieser Begriff bezeichnet im allgemeinen die Fähigkeit, verschiedene Formen anzunehmen. Im Rahmen einer typisierten Sprache wie Eiffel bedeutet dies, daß Größen eines Programmtextes zur Laufzeit auf Exemplare verschiedener Klassen verweisen dürfen. So ist zum Beispiel vom intuitiven Verständnis her jeder Arbeitnehmer auch eine Person – und nicht etwa etwas, was erst durch eine Konvertierung zu einer Person werden kann. Aufgrund des Vererbungskonzepts findet dieser intuitive Zusammenhang in Eiffel ein natürliches Gegenstück: eine Größe p vom Typ PERSON darf zur Laufzeit durchaus auf ein Arbeitnehmer- oder ein Universitätsangestellten-Objekt bezeichnen. Bei Programmiersprachen mit einem starren Typkonzept wäre hierfür eine explizite Konvertierung notwendig 26 . Polymorphismus ist in einer Sprache wie Eiffel leicht zu realisieren, da ja alle Größen eines Klassentyps in Wirklichkeit Verweise auf Objekte sind. Polymorphismus in Eiffel hat daher nichts zu tun mit Objekten, die ihre Form während der Laufzeit ändern, sondern bedeutet nur, daß eine gegebene Größe auf Objekte verschiedener Art verweisen kann. Durch Vererbung wird Polymorphismus also prinzipiell ermöglicht, aber gleichzeitig auch auf ein sinnvolles Maß begrenzt: eine Größe a vom Typ ARBEITNEHMER darf nicht ein einfaches Personenobjekt 26 Eine einzige Ausnahme bilden Zahlen der Typen INTEGER und REAL, die in fast allen Sprachen automatisch ineinander umgewandelt werden, ohne daß es hierzu eines gesonderten Konvertierungsbefehls bedarf.
ezeichnen, denn nicht jede Person ist auch ein Arbeitnehmer. Vererbung ist also ein Kontrollmechanismus für Polymorphismus, der einerseits eine vollständige Klassifizierung aller Objekte ermöglicht und dennoch eine gewisse – der Realität entsprechende Freiheit – zuläßt. Vererbung liefert auch eine Lösung für die am Ende des Abschnitts 3.6.2 angesprochene Problematik, daß Listen, die aus Elementen verschiedener Klassen bestehen, bisher nicht möglich waren. Ohne Vererbung wäre es ausgesprochen schwierig, in einem Bibliothekenverwaltungsystem die unterschiedlichen Arten von Benutzern – Entleiher, Universitätsangestellte, Professoren und Mitarbeiter der Bibliothek – in einer gemeinsamen Liste zu verwalten. Diese Form von Polymorphismus kann nun sehr leicht realisiert werden: man versucht einfach, eine gemeinsame Oberklasse BENUTZER zu definieren, deren Erben die Klassen ENTLEIHER, UNI-ANGESTELLTE, PROFESSOR und MITARBEITER sind, und deklariert die gewünschte Liste als benutzerliste:LIST[BENUTZER]. Die in benutzerliste eingetragenen Verweise dürfen dann, wie in Abbildung 3.33 gezeigt, auf Exemplare aller Erbenklassen von BENUTZER zeigen. Professorenobjekt Studentenobjekt Mitarbeiterobjekt Professorenobjekt ◗❦ ◗ ◗ ◗ ◗ ◗ ◗ ◗ ◗ benutzerliste ◗ ✲ ❆❑ ❆ ❆ ❆ ❆ ❆ ❆ ✁ ✁✁✁✁✁✁✕ Abbildung 3.33: Eine polymorphe Liste ✑✸ ✑✑✑✑✑✑✑✑ ✑ Ein unbeschränkter Polymorphismus ist in Eiffel jedoch nicht möglich, da dies dem Gedanken der Klassifizierung von Objekten in Gruppen mit gemeinsamen Merkmalen widersprechen würde. Eine Zuweisung p:=a ist deshalb durchaus möglich, wenn p vom Typ PERSON und a vom Typ ARBEITNEHMER ist, nicht jedoch a:=p. Im ersten Fall ist nämlich immer sichergestellt, daß p auf ein Objekt der Klasse PERSON bzw. ihrer Nachkommen zeigt, während im zweiten Fall a nach der Zuweisung durchaus auf ein Objekt zeigen könnte, welches die in der Klasse ARBEITNEHMER vereinbarten Merkmale überhaupt nicht kennt 27 . Hinter dieser Einschränkung steht eine weitere grundsätzliche Regel des Typsystems von Eiffel. Entwurfsprinzip 3.8.6 (Regel der Typverträglichkeit) Eine Zuweisung der Form x:=y, wobei x vom Typ A und y vom Typ B ist, ist nur dann zulässig, wenn B konform zu A ist. Gleiches gilt für den Aufruf einer Routine mit formalem Parameter x und aktuellem Parameter y, wobei x vom Typ A und y vom Typ B ist. Der Aufruf ist nur dann zulässig, wenn B konform zu A ist. 27 Die Zuweisung a:=p ist selbst dann verboten, wenn unmittelbar zuvor der Befehl p:=a ausgeführt wurde und p somit tatsächlich auf ein Objekt der Klasse ARBEITNEHMER verweist. Will man einen Verweis an ein Objekt binden, so muß sichergestellt sein, daß dessen Typ mit dem des Verweises verträglich ist. Jede andere Regelung würde nur einen schlechten Programmierstil fördern. Wenn von vorneherein beabsichtigt ist, daß p nur ein Arbeitnehmerobjekt enthalten soll, dann sollte man p entsprechend deklarieren.
- Seite 69 und 70: Der Wert einer Aussage mit mehreren
- Seite 71 und 72: Wichtig ist, daß die Auswahl des W
- Seite 73 und 74: Wir geben hier eine Funktion an, di
- Seite 75: wichtigste formale Sprache zur Besc
- Seite 78 und 79: Wir wollen jedoch deutlich darauf h
- Seite 80 und 81: Buch, sondern sollten besser als ei
- Seite 82 und 83: Viel sinnvoller ist es, bei der Bes
- Seite 84 und 85: Entsprechend ihrer beabsichtigten B
- Seite 86 und 87: Klassen sind rein statische Beschre
- Seite 88 und 89: leeren Verweis (d.h. von machen Per
- Seite 90 und 91: haben wie z.B. “(jahr:INTEGER)”
- Seite 92 und 93: und diese erzeugten Objekte mit Ver
- Seite 94 und 95: Bei der Erzeugung von Objekten mitt
- Seite 96 und 97: über den Namen eines Attributs Wer
- Seite 98 und 99: • Die Veränderung und Auswertung
- Seite 100 und 101: 3.5 Copy- und Referenz-Semantik In
- Seite 102 und 103: 3.5.2 expanded: Klassen mit Copy-Se
- Seite 104 und 105: class LIST[X] creation new feature
- Seite 106 und 107: Dieses Problem wird durch das Konze
- Seite 108 und 109: 3.7.1 Zusicherungen Eiffel logische
- Seite 110 und 111: class ARRAY[X] creation make featur
- Seite 112 und 113: class ARRAY[X] creation make featur
- Seite 114 und 115: formulieren und zu überwachen. Eig
- Seite 116 und 117: 3.8.2 Export geerbter Features Norm
- Seite 118 und 119: Ist also p ein Personenobjekt und a
- Seite 122 und 123: Um die Beschreibung des Typsystems
- Seite 124 und 125: Nachkommenklassen aber folgt entity
- Seite 126 und 127: deferred class LIST[X] feature leng
- Seite 128 und 129: class STUDENT feature universität:
- Seite 130 und 131: Das Problem ist nun, daß beide Elt
- Seite 132 und 133: Prinzipiell wäre es sogar möglich
- Seite 134 und 135: Das bedeutet also, daß die Erbenkl
- Seite 136 und 137: Die eigentliche Montage eines Syste
- Seite 138 und 139: Verständlichkeit der Module: Die L
- Seite 140 und 141: dynamische Semantik: Die dynamische
- Seite 142 und 143: Constant ::= Manifest constant | Id
- Seite 145 und 146: Kapitel 4 Systematische Entwicklung
- Seite 147 und 148: 4.1.2 Grundideen des objektorientie
- Seite 149 und 150: jedoch dringend zu empfehlen, jegli
- Seite 151 und 152: • Ausleihe - Bücher werden nach
- Seite 153 und 154: Der Anwender ist kein echter Klient
- Seite 155 und 156: Es sei an dieser Stelle angemerkt,
- Seite 157 und 158: einen Rechner überprüft werden ka
- Seite 159 und 160: Definition 4.2.3 (Korrektheit von R
- Seite 161 und 162: Programmkonstruktion keine Rolle, d
- Seite 163 und 164: Eine Wertzuweisung entity := Ausdru
- Seite 165 und 166: 4.3.2.1 Die Rolle formaler Paramete
- Seite 167 und 168: Für eine korrekt implementierte Pr
- Seite 169 und 170: { pre} Anweisung1 { p} , { p} Anwei
Definition 3.8.5 (Konformität)<br />
Ein Datentyp B ist genau dann konform zu einem Datentyp A (“B conforms to A”), wenn eine <strong>der</strong> folgenden<br />
Bedingungen erfüllt ist.<br />
1. A und B sind identisch,<br />
2. A ist von <strong>der</strong> Form expanded B o<strong>der</strong> B ist von <strong>der</strong> Form expanded A,<br />
3. A ist REAL o<strong>der</strong> DOUBLE und B ist INTEGER o<strong>der</strong> REAL,<br />
4. A ist eine Klasse ohne generische Parameter und B ist eine Klasse, die A in <strong>der</strong> inherit-Klausel aufführt,<br />
5. A ist von <strong>der</strong> Form G[A1, ..An] und B führt G[B1, ..Bn] in <strong>der</strong> inherit-Klausel auf, wobei G eine generische<br />
Klasse ist und jedes <strong>der</strong> Bi zu Ai konform ist,<br />
6. B ist von <strong>der</strong> Form like anchor und <strong>der</strong> Typ von anchor ist konform zu A,<br />
7. Es gibt einen Typen C mit <strong>der</strong> Eigenschaft, daß B konform ist zu C und C konform zu A.<br />
Eine ausführliche Diskussion von Konformität und weitere Verfeinerungen <strong>der</strong> Definition findet man in<br />
[Meyer, 1992, Kapitel 13].<br />
Vererbung und Redefinition begünstigen einen Softwareentwicklungsstil, <strong>der</strong> sich vollkommen von den bisher<br />
üblichen Vorgehensweisen unterscheidet. Statt jedes Problem ganz von Neuem zu lösen, kann man auf Lösungen<br />
ähnlicher Probleme aufbauen, ihre Dienstleistungen erweitern und gegebenenfalls durch Redefinition für<br />
die spezielle Fragestellung optimieren. Diese Form <strong>der</strong> Wie<strong>der</strong>verwendung bestehen<strong>der</strong> Softwaremodule ist<br />
hochgradig ökonomisch und bescheiden zugleich: sie erkennt die Leistungen an<strong>der</strong>er Softwareentwickler an,<br />
anstatt sie durch eine völlige Neuentwicklung zu ignorieren.<br />
Die Notwendigkeit, hierfür die Gemeinsamkeiten zwischen Gruppen verwandter Daten zu berücksichtigen,<br />
findet ebenfalls eine Antwort: in Netzwerken von Klassen, die durch Vererbung miteinan<strong>der</strong> verbunden sind,<br />
können wir die logischen Beziehungen zwischen diesen Gruppen ausdrücken. Wie<strong>der</strong>verwendbarkeit wird dadurch<br />
geför<strong>der</strong>t, daß die Deklaration eines features soweit wie möglich nach oben verschoben wird, damit<br />
dieses feature in einer großen Anzahl von Nachkommen zur Verfügung steht.<br />
3.8.4 Polymorphismus<br />
Wir haben gesehen, daß durch Vererbung die Wie<strong>der</strong>verwendbarkeit von Softwaremodulen erheblich gesteigert<br />
werden kann. Darüber hinaus hat Vererbung aber noch einen weiteren wichtigen Aspekt, nämlich<br />
Polymorphismus. Dieser Begriff bezeichnet im allgemeinen die Fähigkeit, verschiedene Formen anzunehmen.<br />
Im Rahmen einer typisierten Sprache wie Eiffel bedeutet dies, daß Größen eines Programmtextes zur Laufzeit<br />
auf Exemplare verschiedener Klassen verweisen dürfen.<br />
So ist zum Beispiel vom intuitiven Verständnis her je<strong>der</strong> Arbeitnehmer auch eine Person – und nicht etwa<br />
etwas, was erst durch eine Konvertierung zu einer Person werden kann. Aufgrund des Vererbungskonzepts<br />
findet dieser intuitive Zusammenhang in Eiffel ein natürliches Gegenstück: eine Größe p vom Typ PERSON<br />
darf zur Laufzeit durchaus auf ein Arbeitnehmer- o<strong>der</strong> ein Universitätsangestellten-Objekt bezeichnen. Bei<br />
Programmiersprachen mit einem starren Typkonzept wäre hierfür eine explizite Konvertierung notwendig 26 .<br />
Polymorphismus ist in einer Sprache wie Eiffel leicht zu realisieren, da ja alle Größen eines Klassentyps in Wirklichkeit<br />
Verweise auf Objekte sind. Polymorphismus in Eiffel hat daher nichts zu tun mit Objekten, die ihre<br />
Form während <strong>der</strong> Laufzeit än<strong>der</strong>n, son<strong>der</strong>n bedeutet nur, daß eine gegebene Größe auf Objekte verschiedener<br />
Art verweisen kann. Durch Vererbung wird Polymorphismus also prinzipiell ermöglicht, aber gleichzeitig auch<br />
auf ein sinnvolles Maß begrenzt: eine Größe a vom Typ ARBEITNEHMER darf nicht ein einfaches Personenobjekt<br />
26 Eine einzige Ausnahme bilden Zahlen <strong>der</strong> Typen INTEGER und REAL, die in fast allen Sprachen automatisch ineinan<strong>der</strong><br />
umgewandelt werden, ohne daß es hierzu eines geson<strong>der</strong>ten Konvertierungsbefehls bedarf.