next up previous contents index
Weiter: 14 Low-Level Features Hinauf: 13 Mehrfachvererbung in Zurück: 13.2 Mixins

13.3 Mehrfache Sichtweisen eines Objektes

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;

private

type Inner(Ptr: access Outer) is limited ...

type Outer is limited
record
...
Component: Inner(Outer'ACCESS);
...
end record;

Component des Typs Inner hat eine Access-Diskriminante Ptr, die zur umschließenden Instanz des Records Outer weist. Und das deshalb, weil das Attribut ACCESS, wenn es auf den Namen eines Record-Typs innerhalb seiner Deklaration angewandt wird, auf die aktuelle Instanz des Typs verweist. Wenn wir nun ein Objekt des Typs Outer deklarieren

Obj: Outer;

dann entsteht eine selbstreferenzierende Struktur einer Gestalt, wie sie in Abbildung 13.1 dargestellt ist.

  figure8515
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 null loop
Update(This_Mon.all); -Dispatching-Mechanismus!
This_Mon := This_Mon.Next;
end loop;
end Notify;

Dabei ist Notify eine klassenweite Operation des Typs Monitored_Object, die alle Update-Operationen der Monitore in der verketteten Liste aufruft.

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;

Dann können wir das Objekt beliebig modifizieren und von Zeit zu Zeit das veränderte Molekül mittels

Notify(Medikament);

ausgeben. Eine mögliche interne Konfiguration könnte wie in Abbildung 13.2 aussehen.

  figure8736
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);

Die Implementation könnte wie folgt aussehen:

procedure Update(M: in out Monitor_Mixin) is
-wirgebeneinfachdasWindowneuaus
begin
Display(M.Win.all);
end Update;

Und jetzt mixen wir diesen Monitor_Mixin in einen beliebigen Window-Typ, indem wir schreiben:

type Window_That_Monitors is new My_Window with
record
Mon: Monitor_Mixin(Window_That_Monitors'ACCESS);
end record;

Die innere Komponente Mon hat eine Access-Diskriminante, die zum äußeren Typ verweist. Seine Monitor-Komponente wiederum kann nun, wie in Abbildung 13.3 gezeigt, in die Liste eingehängt werden.

  figure8874
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.



next up previous contents index
Weiter: 14 Low-Level Features Hinauf: 13 Mehrfachvererbung in Zurück: 13.2 Mixins

Johann Blieberger
Wed Feb 11 09:58:52 MET 1998