Obwohl schon häufig erkannt worden ist, daß es sehr sinnvoll ist, zu einer Abstraktion mehrere Implementation schaffen zu können, die auf unterschiedliche Eigenschaften der Objekte eingehen, wie zum Beispiel dicht oder dünn besetzte Matrizen, war ein solches Vorgehen erstmals in C++ möglich. Nun bietet auch Ada diese Möglichkeit.
Eine Spezifikation eines abstrakten Mengen-Paketes könnte etwa wie folgt aussehen.
Ein Beispiel für so einen abgeleiteten Typ ist folgender.
procedure Take(From: in out Bit_Set;
with Abstract_Sets;
package Bit_Vector_Sets is
type Bit_Set is new Abstract_Sets.Set with private;
-neueDefinitionderOperationen
function Empty return Bit_Set;
function Unit(Element: Set_Element) return Bit_Set;
function Union(Left, Right: Bit_Set) return Bit_Set;
function Intersection(Left, Right: Bit_Set) return Bit_Set;
Element: out Set_Element);
private
Bit_Set_Size: constant integer := 64;
type Bit_Vector is
array (Set_Element range 0 .. Bit_Set_Size-1) of Boolean;
pragma Pack(Bit_Vector);
type Bit_Set is new Abstract_Sets.Set with
record
Data: Bit_Vector;
end record;
end Bit_Vector_Sets;
package body Bit_Vector_Sets is
function Empty return Bit_Set is
begin
return (Data =
end;
function Unit(Element: Set_Element) return Bit_Set is
S: Bit_Set := Empty;
begin
S.Data(Element) := True;
return S;
end;
function Union(Left, Right: Bit_Set) return Bit_Set is
begin
return (Data =
end;
end Bit_Vector_Sets;
Eine alternative Implementierung für dünn besetzte Mengen könnte dann eine Listenverwaltung der Elemente verwenden.
procedure Take(From: in out Linked_Set;
with Abstract_Sets;
package Linked_Sets is
type Linked_Set is new Abstract_Sets.Set with private;
-neueDefinitionderOperationen
function Empty return Linked_Set;
function Unit(Element: Set_Element) return Linked_Set;
function Union(Left, Right: Linked_Set) return Linked_Set;
function Intersection(Left, Right: Linked_Set) return Linked_Set;
Element: out Set_Element);
private
type Element;
type Element_Ptr is access all Element;
type Element is
record
the_Element: Set_Element;
the_next: Element_Ptr;
end record;
type Linked_Set is new Abstract_Sets.Set with
record
first_Element: Element_Ptr;
end record;
end Linked_Sets;
package body Linked_Sets is
function Empty return Linked_Set is
begin
return (first_Element =
end Empty;
function Unit(Element: Set_Element) return Linked_Set is
S: Linked_Set;
begin
S.first_Element := new Element'(Element,null);
return S;
end Unit;
end Linked_Sets;
Wir können dann ein Programm schreiben, das beide Formen von Mengen gleichzeitig verwendet, und wir können eine Konversion zwischen den beiden Darstellungen wie folgt durchführen.
procedure Convert(From: in Set'Class; To: out Set'Class) is
Temp: Set'Class := From;
Elem: Set_Element;
begin
-builduptargetset,oneelementatatime
To := Empty;
while Temp
Take(Temp, Elem);
To := Union(To, Unit(Elem));
end loop;
end Convert;
Abschließend sei noch darauf hingewiesen, daß das abstrakte Set-Paket auch generisch sein könnte, was die Wiederverwendbarkeit des Paketes noch steigern würde.
Johann Blieberger