Vereinigungstypen, Varianten


Gelegentlich will man mehrere Datentypen mit gleicher Bedeutung, aber unterschiedlichen internen Formats zu einem Vereinigungstyp zusammenfassen, der logisch die disjunkte Vereinigung der gegebenen Typen ist. Der Zugriff auf ein Datenelement hängt dann davon ab, in welchem internen Format die Daten abgelegt sind, und daher muß jedes Datenelement zusätzlich eine Angabe über den Grundtyp enthalten, die zur Laufzeit des Programms ausgewertet werden kann.

Modula 2 bietet dazu Verbunde mit Varianten an. Ein solcher Verbund besitzt einen gemeinsamen Teil (er kann leer sein), ein Schalterfeld von einem geeigneten skalaren Typ, sowie mehrere alternative Fortsetzungen des gemeinsamen Teils. Der aktuelle Inhalt des Schalterfeldes gibt an, welche Variante gerade aktuell ist. Die Varianten belegen denselben  Speicherplatz.

Beispiel:  Punkte in der Ebene können wahlweise durch Kartesische Koordinaten oder durch Polarkoordinaten angegeben werden. Dies läßt sich durch folgenden Vereinigungstyp ausdrücken:

TYPE Punkt = RECORD CASE kp: (K, P) OF
                         K: x, y: REAL; |
                         P: r, phi;
                    END;
             END;
Zur Laufzeit kann der Verbund, der einen Punkt beschreibt, aus den Feldern (kp, x, y) bestehen, dann muß kp=K gelten; oder aber er besteht aus (kp, r, phi), dann muß kp=P sein. Programme, die mit solchen Verbunden arbeiten, können durch Abfrage des Schalterfeldes kp feststellen, welche Darstellung vorliegt. Ein Zugriff über die Selektoren der anderen Variante ist dann natürlich unsinnig.

In Sonderfällen kann das Schalterfeld fehlen (allerdings nicht seine Typangabe!) dann muß das Programm anderswo her wissen, welche Variante gerade gültig ist. Generell muß davon abgeraten werden; solche Programme sind extrem schwer korrekt zu bekommen.

In diesem Falle ist es möglich, und es kann sogar manchmal sinnvoll sein, auf denselben Dateninhalt über Selektoren verschiedener Varianten zuzugreifen. So kann man mit der Typvereinbarung

TYPE ptrval = RECORD CASE : BOOLEAN OF
                       TRUE: ptr: liste; |
                       FALSE: val: CARDINAL;
                     END;
              END;
auf die einem Pointerwert vom Typ liste  entsprechende interne Adressen-Darstellung als CARDINAL-Wert zugreifen (vorausgesetzt, der Umfang von CARDINAL ist groß genug), und sogar neue Pointer-Werte erzeugen. Das ist etwa notwendig, wenn man selbst eine Halden-Verwaltung schreiben muß; natürlich ist ein solches Programm extrem vom Rechnertyp abhängig, und man muß ganz genau wissen, was man tut. Für Menschen mit schwachen Nerven ist das nichts!
zurück | Inhalt | Index | vor | Vorlesung

Klaus Lagally, 22. Februar 2000, 19:36