7. Programmeinheiten
 
zurück
7.13.1 Aufbau generische Einheiten


Eine generische Einheit ist eine Programmeinheit, die entweder ein generisches Unterprogramm (generische Funktion oder generische Prozedur) oder ein generisches Paket ist. Sie ist eine parametrierte Schablone, aus der verschiedene Programmeinheiten, Unterprogramme bzw. Pakete, erzeugt (ausgeprägt) werden können.

Bestimmte Einzelheiten werden offengelassen und durch die sogenannten generischen formalen Parameter repräsentiert. Als Parameter übergeben werden können: Objekte, Typen, Unterprogramme und Pakete. Diese Parameter für generische Einheiten werden generische formale Objekte, Typen, Unterprogramme und Pakete genannt. Bei der Ausprägung (Instantiierung) müssen diese Parameter besetzt werden.

Wie jede andere Programmeinheit besteht eine generische Programmeinheit aus einer Spezifikation und einem Rumpf. Im Gegensatz zu Paketen hat jede generische Einheit einen Rumpf. Zur Spezifikation einer generischen Einheit gehört:
  • der generische formale Teil - das ist die Parameterliste der generischen Einheit und
  • die Unterprogramm- oder Paketspezifikation.
Generische Deklaration

Eine generische Einheit wird durch eine generische Deklaration (generic_declaration <BNF>) spezifiziert.

generic
<generische Formalparameter>
procedure <Prozedurname> <Parameterliste>;

generic
<generische Formalparameter>
package <Paketname>
<Paketspezifikation>
end <Paketname>;

Eine generische Einheit ist entweder ein generisches Unterprogramm oder ein generisches Paket. Die generische Deklaration baut daher auf der Deklaration eines Unterprogramms/Pakets auf. Darüber hinaus hat sie einen generischen formalen Teil (generic_formal_part <BNF>), um die generischen Formalparameter zu spezifizieren. Dieser Teil beginnt mit dem Schlüsselwort "generic". Darauf folgt eine Unterprogramm- (subprogram_specification <BNF>) oder Paketspezifikation (package_specification <BNF>).

Ein generischer Formalparameter kann nicht nur ein Objekt sein, sondern auch ein Typ, ein Unterprogramm oder ein Paket.

Die einzelnen Bestandteile des generisch formalen Teils werden auch
  • generisches formales Objekt,
  • generischer formaler Typ,
  • generisches formales Unterprogramm und
  • generisches formales Paket genannt.
    Diese Langform der Bezeichnung von generischen Formalparametern muß insbesondere für Unterprogramme und Pakete verwendet werden, um die Begriffe
  • generisches Unterprogramm/Paket und
  • generisches formales Unterprogramm/Paket
    gegeneinander abzugrenzen. Während das generische Unterprogramm/Paket die generische Einheit an sich ist, ist ein generisches formales Unterprogramm/Paket ein generischer formaler Parameter.
Beispiele für generische formale Teile:

generic -- parameterlos

generic
   Size : Natural; -- formales Objekt

generic
    Länge : Integer := 200; -- formales Objekt mit Vorbesetzung
    Fläche : Integer := Länge * Länge; -- formales Objekt mit Vorbesetzung

generic
   type Element is private; -- formaler Typ
   type Index is (<>); -- formaler Typ
   type Reihe is array(Index range <>) of Element; -- formaler Typ
   with function "<" (X, Y : Element) return Boolean; -- formales Unterprogramm



Beispiele für generische Deklarationen von generischen Unterprogrammen:

generic
   type Element is private;
procedure Vertausche(U, V : IN OUT Element);

generic
   type Element is private;
   with function "*" (U, V : Element) return Element is <>;
function Quadrat (X : Element) return Element;



Beispiel für die generische Deklaration eines generischen Pakets:

generic
   type Element is private;
   type Vektor is array (Positive range <>) of Element;
   with function Summe (X, Y : Element) return Element;
package Vektoren is
   function Summe (A, B : Vector) return Vektor;
   function Summe_aller_Elemente (A : Vector) return Element;
   Längen_Fehler : exception;
end Vektoren;


Der Rumpf einer generischen Einheit ist eine Schablone für die Rümpfe der Instanzen. Die Syntax eines generischen Rumpfes entspricht der eines vergleichbaren nicht generischen Rumpfes. Der generische Rumpf unterscheidet sich durch die Verwendung der generischen formalen Parameter. Implizit wird durch eine Instantiierung der Rumpf einer neuen Programmeinheit erzeugt. An die Stelle der Formalparameter treten in diesem neuen Rumpf die Aktualparameter.

Beispiel eines generischen Prozedurrumpfs:

procedure Vertausche (U, V : IN OUT Element) is
   T : Element; -- der generische formale Typ
begin
   T := U;
   U := V;
   V := T;
end Vertausche;

Beispiel eines generischen Funktionsrumpfes:

function Quadrat (X : Element) return Element is
begin
   return X * X; -- der formale Operator "*"
end Quadrat;


Beispiel eines generischen Paketrumpfes:

package body Vektoren is
   function Summe (A, B : Vektor) return Vektor is
      Ergebnis : Vektor(A'Range); -- der formale Typ Vektor
      Abstand : constant Integer := B'First - A'First;
   begin
      if A'Length /= B'Length then
         raise Längen_Fehler;
      end if;
      for N in A'Range loop
         Ergebnis(N) := Summe(A(N), B(N + Abstand)); -- die formale Funktion Summe
      end loop;
      return Ergebnis;
   end Summe;

   function Summe_aller_Elemente (A : Vektor) return Element is
      Total : Element := A(A'First); -- der formale Typ Element
   begin
      for N in A'First + 1 .. A'Last loop
         Total := Summe(Total, A(N)); -- die formale Function Summe
      end loop;
      return Total;
   end Summe_aller_Elemente;
end Vektoren;

Generische Einheiten sind als Schablonen nicht lauffähig! Um generische Einheiten zu benutzen und damit lauffähigen Code erzeugen müssen generische Einheiten mit aktuellen Parametern versorgt werden, d.h. eine sogenannte Instanz bilden.

Die Instanz einer generischen Einheit ist das Ergebnis einer generischen Instantiierung mit bestimmten Aktualparametern für die generischen Formalparameter.

Bei der generischen Instantiierung sind grundsätzlich alle generischen Parameter mit entsprechenden Aktualparametern zu besetzen; es sei denn, es gibt eine Vorbesetzung für einen generischen Parameter. Vorbesetzungen sind für generische formale Unterprogramme möglich.

Beispiele für generische Instantiierungen:

procedure Auswechseln is new Vertausche (Element => Integer);
-- eine Instanz kann auch überladen werden
procedure Auswechseln is new Vertausche (Character);

function Integer_Quadrat is new Quadrat (Integer);
function Matrix_Quadrat is new Quadrat (Element => Matrix, " *" => Matrix_Product);
-- nochmal in anderer Schreibweise
function Matrix_Quadrat is new Quadrat (Matrix, Matrix_Product);

package Integer_Vektoren is new Vektoren (Integer, Tabelle, "+");
package Integer_Vektoren is new Vektoren (Element => Integer, Vektor => Tabelle, Summe => "+");

Beispiele für den Gebrauch von Instanzen:

Auswechseln (A, B);
A := Integer_Quadrat(A);
---
T : Tabelle(1 .. 5) := (10, 20, 30, 40, 50);
N : Integer := Integer_Vektoren.Summe_aller_Elemente (T); -- 150
---
use Integer_Vektoren;
M : Integer := Summe_aller_Elemente (T); -- 150

Die so entstandenen Programmeinheiten werden Instanzen der
generischen Einheiten genannt. Die Instanz eines generischen Unterprogramms ist ein Unterprogramm, die Instanz eines generischen Pakets ist ein Paket.


 
zurück
 Index   Ada Tour - Dokumentation  
© 2003 Förderverein Ada Deutschland e.V.