Schließlich gibt es auch Mehrfachvererbung, wo die Nachfolgerklasse wirklich von mehreren Klassen abgeleitet wird und wo Anwender dieser Klasse sie als irgendeine ihrer Vorgängerklassen ,,sehen`` wollen. In Ada ist es möglich, das zu erreichen, indem man Access-Diskriminanten einsetzt.
Mit Access-Diskriminanten kann man erreichen, daß eine Komponente eines Records auf den Record verweist, der ihn umschließt. Damit kann man komplexe, verkettete Strukturen errichten und mehrfache Sichtweisen einer Struktur ermöglichen. Betrachten wir beispielsweise folgendes Programmfragment
type Outer is limited private;
Obj: Outer;
Abbildung 13.1: Eine selbstreferenzierende Struktur
Allerdings kann man diese Struktur nicht damit vergleichen, wenn etwa eine Komponente sich selbst aufgrund einer Zuweisung referenziert. Alle Instanzen des Typs Outer referenzieren sich selbst und Ptr kann seinen Wert nicht ändern, da Diskriminanten konstant sind.
So ein einfaches Beispiel bringt nicht viel; wir werden daher ein etwas komplizierteres studieren. Wir nehmen an, wir hätten ein komlexes organisches Molekül, das wir über verschiedene Monitore darstellen wollen. Unsere Datenstruktur wird so beschaffen sein, daß die einzelnen Monitore linear verkettet sind, jeder Monitor aber direkten Zugriff auf das Molekül besitzt, um es darstellen zu können.
type Monitor;
type Monitor_Ptr is access all Monitor'CLASS;
type Monitored_Object is abstract tagged limited
record
First: Monitor_Ptr; -dererstederListederMonitoren
-andereKomponentenkoennendurchTyperweiterung
-spaeterhinzugefuegtwerden
end record;
type Monitored_Object_Ptr is access all Monitored_Object'CLASS;
type Monitor is abstract tagged limited
record
Next: Monitor_Ptr;
Obj: Monitored_Object_Ptr;
-weiterKomponentenkoennenentsprechendden
-BeduerfnissendereinzelnenMonitore
-ueberTyperweiterunghinzugefuegtwerden
end record;
procedure Update(M: in out Monitor) is abstract;
procedure Notify(MO: Monitored_Object'CLASS) is
This_Mon: Monnitor_Ptr := MO.First;
begin
while This_Mon
Update(This_Mon.all); -Dispatching-Mechanismus!
This_Mon := This_Mon.Next;
end loop;
end Notify;
Unser Objekt, das das Molekül representiert, habe den Typ Molecule.
type Monitored_Molecule is new Monitored_Object with
record
M: Molecule;
end record;
Medikament: Monitored_Molecule;
Notify(Medikament);
Abbildung 13.2: Eine verkettete Liste von Monitoren
Jetzt wollen wir annehmen, daß wir eines unserer Windows von vorhin verwenden wollen, um unser Molekül darzustellen. Wir benötigen also ein Objekt, das sich einerseits wie ein Window verhält und andererseits wie ein Monitor. Zunächst definieren wir ein Mixin, das ein Monitor ist und definieren seine Update-Operation neu.
type Monitor_Mixin(Win: access Basic_Window'CLASS) is
new Monitor with null record;
procedure Update(M: in out Monitor_Mixin);
procedure Update(M: in out Monitor_Mixin) is
-wirgebeneinfachdasWindowneuaus
begin
Display(M.Win.all);
end Update;
type Window_That_Monitors is new My_Window with
record
Mon: Monitor_Mixin(Window_That_Monitors'ACCESS);
end record;
Abbildung 13.3: Ein Window in der Monitor-Liste
Wenn nun Notify mit dem Molekül aufgerufen wird, bewirkt das, daß verschiedene Update-Operationen angestoßen werden. Die Update-Operation des Typs Monitor_Mixin ruft Display für den Typ Window_That_Monitors auf, dem es als Teil angehört, und dieser hat alle Information über das Window und darüber, ein Monitor zu sein.
Die vorgeführten Beispiele dieses Abschnittes belegen, daß Ada auch für viele wichtige Anwendungen geeignet ist, die mehrfache Vererbung voraussetzen.
Johann Blieberger