7. Programmeinheiten
 
zurück
7.11.1 Paketspezifikation


Die Paketspezifikation legt fest, welche Programmkonstrukte dem Anwender eines Pakets zur Verfügung gestellt werden und wie diese Konstrukte zu verwenden sind. Es ist nicht wichtig, wie diese Programmkonstrukte im einzelnen implementiert sind (information hiding).


Eine Paketspezifikation hat die Form:

package <paket_name> is
< Vereinbarungen, z. B. Spezifikationen von untergeordneten Programmeinheiten>
end;


Nach dem Schlüsselwort "package" folgt der Bezeichner für das Paket und dann nach dem Schlüsselwort "is" der sichtbare Teil des Pakets.

Hier erscheinen nacheinander die Spezifikationen der Konstrukte, die das Paket zur Verfügung stellt: Objekte, Typen etc.

Im folgenden Beispiel werden in der Paketspezifikation für das Paket "Rationale_Zahlen" ein Typ "Rational" und zwei Operationen "=" und "/" angelegt, die Objekte dieses Typs bearbeiten können.

Das Paket kann zum Deklarieren, Erzeugen und Vergleichen von Objekten vom Typ "Rational" verwendet werden. Die Paketspezifikation enthält ausreichend Informationen, um Objekte vom Typ "Rational" zu verwenden.

package Rationale_Zahlen is type Rational is record
   Zaehler : Integer;
   Nenner : Positive;
end record;

function "=" (X,Y: Rational) return Boolean;
function "/" (X,Y: Integer) return Rational; -- zum Erzeugen einer rationalen Zahl
-- ...
end Rationale_Zahlen;

Eine Anwendung für dieses Paket könnte wie folgt aussehen:

with Rationale_Zahlen;
procedure Teste_Rationale_Zahlen is
   -- Deklarieren und Initialisieren von 2 rationalen Zahlen
   Zahl1: Rationale_Zahlen.Rational := Rationale_Zahlen."/" (1,2);
   Zahl2: Rationale_Zahlen.Rational := Rationale_Zahlen."/" (3,4);
begin
   -- Vergleich der beiden rationalen Zahlen
   if Rationale_Zahlen."=" (Zahl1, Zahl2) then
   -- ...
   end if; -- direkter Zugriff auf die Komponenten des Typs Rational ist möglich
   Zahl1.Zaehler := 5;
   Zahl1.Nenner := 6;
end;

Eine Paketspezifikation kann neben den nach außen sichtbaren Vereinbarungen im sichtbaren Teil des Pakets einen optionalen privaten Teil haben, der nach außen hin nicht zugreifbare Vereinbarungen enthält.
Der private Teil dient dazu, Eigenschaften, die außerhalb des Pakets verwendet werden, von den Eigenschaften, deren Gebrauch auf das
Paket selbst beschränkt ist, zu trennen.

Wenn eine Paketspezifikation einen privaten Teil besitzt, dann wird sie wie folgt erweitert:

package <paket_name> is
<Vereinbarungen, z. B. Spezifikationen von untergeordneten Programmeinheiten>
private
<privater Teil>
end;

Der private Teil eines Pakets befindet sich am Ende der Paketspezifikation und wird mit dem Schlüsselwort "private" eingeleitet. Vom Schlüsselwort "private" bis zum Schlüsselwort "end" sind alle Angaben von außen nicht zugänglich. Daher liegt dem Benutzer mit der Paketspezifikation zwar der private Teil des Pakets vor, er kann jedoch die im privaten Teil angegebenen Deklarationen nicht verwenden.

Der private Teil gehört dennoch zur Paketspezifikation, weil ein Paket neben der logischen Gliederung auch die Aufgabe hat, eine getrennt übersetzbare Einheit zu sein. Für den Übersetzer muß ein Typ vollständig bekannt sein, wenn er in einer Spezifikation verwendet wird.

Der private Teil eines Pakets wird verwendet, um private Typen oder private Erweiterungen zu deklarieren.

Die Deklaration eines privaten Typs oder einer privaten Erweiterung erfolgt in zwei Schritten:

a) Deklarieren einer partiellen Sicht auf den Typ (private_type_declaration <BNF>) bzw. die Erweiterung (private_extension_declaration <BNF>) im sichtbaren Teil des Pakets,

b) Vervollständigung (im Sinne der Übersetzbarkeit) der Typdefinition im privaten Teil des Pakets.

Deklarieren der partiellen Sicht:
Für einen privaten Typ wird im Vereinbarungsteil der Paketspezifikation lediglich der Typbezeichner eingeführt, als Typdefinition steht der Hinweis "private". Die Typdefinition wird im privaten Teil nachgetragen.

type <Typbezeichner> [<Diskriminante>] is [[abstract] tagged] [limited] private;

type <Typbezeichner> [<Diskriminante>] is
[abstract] new <Elterntyp> with private;


Beispiele:

type Rational is private;
type Schluessel is private;
type Datei_Typ is limited private;


Das Wort "private" dient in der Paketspezifikation zum einen als Platzhalter für die Typdefinition, zum anderen leitet es den privaten Teil der Schnittstelle ein.

Vervollständigung der Typdefinition:
Im privaten Teil einer Paketspezifikation findet die Vervollständigung einer privaten Typdefinition oder privaten Erweiterung statt.
Die im sichtbaren Teil der Paketspezifikation mit dem Schlüsselwort "private" abgekürzte Typdefinition wird hier nachgeholt.


Beispiel:

package Schluessel_Manager is
   type Schluessel is private;
   --...
private
   type Schluessel is new Natural;
   --...
end Schluessel_Manager;

Operationen auf privaten Typen

Bei privaten Typen sind die im sichtbaren Teil der Paketspezifikation auftretenden Angaben außerhalb des Pakets verwendbar. d. h. der Typname und die in der Paketspezifikation vereinbarten Unterprogramme, die mit diesem Typ operieren. Darüber hinaus dürfen für private Typen die für beliebige Typen vorhandenen Operationen:

  • Wertzuweisung,
  • Gleichheit,
  • Ungleichheit
außerhalb des Pakets angewandt werden. Im Rumpf des Pakets, das die Deklaration des privaten Typs enthält, sind die strukturellen Details eines privaten Typs uneingeschränkt verwendbar.

Nicht erlaubt für den Paketanwender ist:
  • Verwendung der Struktur eines privaten Typs.
Erlaubt sind:
  • Deklaration eines oder mehrerer Objekte des privaten Typs,
  • Verwendung der vordefinierten Operationen Wertzuweisung (":="), Gleichheit("=")- und
    Ungleichheit("/=") ist möglich (Kopieren eines Objekts auf ein anderes, Vergleichen von zwei
    Objekten),
  • Bearbeitung dieser Objekte, insbesondere über die Operationen ":=", "=" und "/="
    hinausgehende Bearbeitung, mit den im Paket definierten Operationen auf den privaten Typ.
In dem folgenden Beispiel wird die Typdeklaration mit einem privaten Teil gestaltet.

package Rationale_Zahlen is
   type Rational is private;
   function "=" (X,Y: Rational) return Boolean;
   function "/" (X,Y: Integer) return Rational; -- zum Erzeugen einer rationalen Zahl
   -- ...
private
   type Rational is record
     Zaehler : Integer;
     Nenner : Positive;
    end record;
end Rationale_Zahlen;


Die Erweiterung des Beispiels um den privaten Teil ändert den Programmtext nur wenig. Die eigentliche Veränderung liegt in der Einschränkung des Zugriffs.

with Rationale_Zahlen;
procedure Teste_Rationale_Zahlen is
   -- Deklarieren und Initialisieren von 2 rationalen Zahlen
   Zahl1: Rationale_Zahlen.Rational := Rationale_Zahlen."/" (1,2);
   Zahl2: Rationale_Zahlen.Rational := Rationale_Zahlen."/" (3,4);
begin
   -- Vergleich der beiden rationalen Zahlen
   if Rationale_Zahlen."=" (Zahl1, Zahl2) then
   -- ...
   end if;
   -- direkter Zugriff auf die Komponenten des Typs Rational ist NICHT möglich
   -- Zahl1.Zaehler := 5; -- illegal
   -- Zahl1.Nenner := 6; -- illegal
end;

Es ist nach wie vor möglich, Objekte vom Typ Rational zu deklarieren und vom Paket zur Verfügung gestellte Operationen auf diesen Objekten durchzuführen. Der Zugriff auf die Struktur eines privaten Typs ist nicht möglich.

Zur Kontrolle über alle Operationen, die auf Objekte dieser privaten Typen angewendet werden, können limitierte
private Typen deklariert werden.

Die Wertzuweisung und die vordefinierten Gleichheits- und Ungleichheitsabfragen können außerhalb des Pakets, das einen privaten Typ definiert, verboten werden, indem man zusätzlich das Schlüsselwort "limited" vor die Angabe "private" im sichtbaren Teil der Schnittstelle schreibt. Ein solcher Typ wird als "limitiert privater Typ" bezeichnet.

Es gibt neben den limitierten privaten Typen weitere limitierte Typen:
  • Typen mit dem Schlüsselwort "limited" in ihrer Definition,
  • einen Prozeß oder einen geschützten Typ,
  • ein zusammengesetzten Typ mit einer Komponente, deren Typ ein limitierter Typ ist.
Allen limitierten Typen ist gemeinsam:
  • die Wertzuweisung (":=") ist verboten,
  • es gibt keine vordefinierten Gleichheit("=")- und Ungleichheit("/=")-Operationen.
Nicht erlaubt für den Paketanwender sind:
  • Verwendung der Struktur eines privaten Typs.
  • Wertzuweisung (":="), Gleichheit("=")- und Ungleichheit("/=")-Operationen sind nicht möglich.
Erlaubt sind:
  • Deklaration eines oder mehrerer Objekte des limitierten Typs,
  • Bearbeitung dieser Objekte mit den im Paket definierten Operationen auf den limitierten
    privaten Typ.
Beispiel:

package IO_Paket is
   type Datei_Typ is limited private; procedure Oeffnen (F : in out Datei_Typ);
   procedure Schliessen(F : in out Datei_Typ);
   procedure Lesen (F : in Datei_Typ; Item : out Integer);
   procedure Schreiben(F : in Datei_Typ; Item : in Integer);
private
   type Datei_Typ is record
      Interner_Name : Integer := 0;
   end record;
end IO_Paket;

package body IO_Paket is
   -- ...
   procedure Oeffnen (F : in out Datei_Typ) is ... end;
   procedure Schliessen(F : in out Datei_Typ) is ... end;
   procedure Lesen (F : in Datei_Typ; Item : out Integer) is ... end;
   procedure Schreiben(F : in Datei_Typ; Item : in Integer) is ... end;
begin
   -- ...
end IO_Paket;

Außerhalb des Pakets "IO_Paket" kann eine Variable vom Typ "Datei_Typ" verwendet werden. Nur mit den Prozeduren "Oeffnen" und "Schliessen" des Pakets kann diese Variable verändert werden, da die Struktur der Variablen außerhalb des Pakets nicht zugreifbar ist. So sind keine vordefinierten Operationen auf dieser Variablen möglich: kein Vergleich von zwei Variablen dieses Typs, kein Kopieren des Inhalts der Variablen.

Enthält die Paketspezifikation die Konstante eines privaten Typs, so muß eine offene Konstante deklariert werden.

Enthält die Paketspezifikation die Konstante eines privaten Typs, so kann der Wert diesem Objekt im sichtbaren Teil der Schnittstelle nicht mitgegeben werden, da dieser Wert Angaben über die Struktur enthält. Dies muß im privaten Teil nachgeholt werden. Man spricht daher von offenen Konstanten ("deferred constants").

Offene Konstanten treten nicht nur im Zusammenhang mit der privaten Typdeklaration auf, sondern auch, um sie mittels Anbindung aus einer anderen Sprache zu importieren.

Die Deklaration offener Konstanten ist eine Objektvereinbarung (object_declaration <BNF>) mit dem Schlüsselwort "constant" aber ohne Initialisierungsausdruck (expression <BNF>). Sie erfordert eine Vervollständigung, die
  • eine vollständige Konstantendeklaration oder
  • das Pragma "Import" sein kann.
Beispiele:

-- Offene Konstante zu einem privaten Typ:
package Schluessel_Manager is
   type Schluessel is private;
   Leerer_Schluessel : constant Schluessel;
   -- ...
private
   type Schluessel is new Natural;
   Leerer_Schluessel : constant Schluessel := Natural'First;
   --...
end Schluessel_Manager;

-- Offene Konstante, die aus einer anderen Sprache importiert wird:
CPU_Bezeichnung : constant String(1..8);
pragma Import(Assembler, CPU_Bezeichnung, Link_Name => "CPU_ID");



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