Logo

Marco Cantù's
Essential Pascal

Kapitel 4
Benutzerdefinierte Datentypen

Die Fähigkeit, neue Datentypen im Programm zu definieren ist, zusammen mit dem Begriff des Typs ist eine der größten Ideen, die durch die Sprache Pascal eingeführt wurde. Programmierer können ihre eigenen Datentypen unter Verwendung einer Typdeklaration definieren, wie z.B. Teilbereichstypen, Array-Typen, Record-Typen, Aufzählungstypen, Zeigertypen, und Mengentypen. Der wichtigste benutzerdefinierte Datentyp ist allerdings die Klasse, welche Teil der objektorientierten Erweiterungen von Objekt-Pascal ist und in diesem Buch nicht behandelt wird.

Wenn Sie denken, dass Typdelarationen in vielen Programmiersprachen üblich sind, so liegen Sie richtig. Aber Pascal war die erste Sprache, die diese Idee auf eine formale und sehr präzise Weise einführte. Es gibt immer noch sehr wenige Sprachen, die so vielen Mechanismen anbieten, um neue Datentypen zu definieren.

Benannte und unbenannte Typen

Diese Typen können mit einem Namen für die spätere Verwendung versehen werden oder direkt auf eine Variable angewendet werden. Wenn Sie einen Namen für einen Typ vergeben, so müssen sie dies in einem speziellen Abschnitt des Codes vornehmen, wie im folgenden:

type
  // Teilbereichsdefinition
  Uppercase = 'A'..'Z';

  // Array-Definition
  Temperatures = array [1..24] of Integer;

  // Record-Definition
  Date = record
    Month: Byte;
    Day: Byte;
    Year: Integer;
  end;

  // Definition eines Aufzählungstyps
  Colors = (Red, Yellow, Green, Cyan, Blue, Violet);

  // Mengendefinition
  Letters = set of Char;

Ähnliche Konstrukte zur Typdefinitionen können verwendet werden, um eine Variable ohne einen expliziten Typnamen zu definieren, wie im folgenden Code:

var
  DecemberTemperature: array [1..31] of Byte;
  ColorCode: array [Red..Violet] of Word;
  Palette: set of Colors;

Hinweis: Im Allgemeinen sollten Sie die Verwendung von unbenannten Typen wie im obigen Code vermeiden, da Sie diese nicht als Parameter an Routinen übergeben können sowie auch keine weiteren Variablen des selben Typs vereinbaren können. Die Typkompatibilitätsregeln von Pascal basieren auf Typnamen, nicht auf der tatsächlichen Definition eines Typs. Zwei Variablen von zwei identischen Typen sind dennoch nicht kompatibel, es sei denn ihr Typ hat exakt den selben Namen und unbenannte Typen werden durch den Compiler interne Namen zugewiesen. Gewöhnen Sie sich an jedesmal einen Datentyp zu definieren, wenn Sie eine komplexe Variable benötigen und sie werden die Zeit nicht bereuen, die Sie dafür benötigt haben.

Doch was bedeuten diese Typdefinitionen? Nun -- ich werde all jenen, die nicht vertraut sind mit den Typdeklarationen in Pascal, einige Beschreibungen geben. Ich werde auch versuchen, den Unterschied zu gleichartigen Konstrukten in anderen Programmiersprachen hervorzuheben, so dass es interessant sein könnte, die folgenden Abschnitte zu lesen, auch wenn Sie mit den oben angegebenen beispielhaften Typdefinitionen bereits vertraut sind. Abschließend werde ich ein paar Delphi-Beispiele zeigen und einige Werkzeuge vorstellen, die Ihnen gestatten, auf Typinformationen dynamisch zuzugreifen.

Teilbereichstypen

Ein Teilbereichstyp definiert einen Bereich von Werte innerhalb des Wertebereichs eines anderen Typen (daher der Name Teilbereich). Sie können einen Teilbereich eines Integer-Typen definieren, von 1 bis 10 oder von 100 bis 1000, oder Sie können auch einen Teilbereich des Char-Typs definieren, wie in:

type
  Ten = 1..10;
  OverHundred = 100..1000;
  Uppercase = 'A'..'Z';

Bei der Definition eines Teilbereichs müssen Sie nicht den Namen des Basistyps angeben. Sie müssen nur zwei Konstanten dieses Typs vorgeben. Der ursprüngliche Typ muss ein ordinaler Typ sein, und der resultierende Typ wird ein weiterer ordinaler Typ.

Wenn Sie einen Teilbereich definiert haben, so können sie uneingeschränkt Werte innerhalb dieses Bereichs zuweisen. Dieser Code ist gültig:

var
  UppLetter: UpperCase;
begin
  UppLetter := 'F';

Aber dieser ist es nicht:

var
  UppLetter: UpperCase;
begin
  UppLetter := 'e'; // Übersetzungszeitfehler

Das Schreiben des obigen Codes führt zu einen Fehler zur Übersetzungszeit, "Konstantenausdruck verletzt untere Grenzen". Wenn Sie statt dessen den folgenden Code schreiben:

var
  UppLetter: Uppercase;
  Letter: Char;
begin
  Letter :='e';
  UppLetter := Letter;

so wird es Delphi übersetzen. Zur Laufzeit, wenn Sie die Compileroption Bereichsüberprüfung angegeben haben (auf der Seite Compiler des Dialogs Projektoptionen) werden Sie eine Meldung Fehler bei Bereichsprüfung erhalten.

Hinweis: Ich empfehle Ihnen, dass Sie diese Compileroption einschalten, während Sie ein Programm entwickeln, so wird es robuster und einfacher zu debuggen, da Sie im Falle eines Fehlers eine explizite Fehlermeldung erhalten und kein unbestimmtes Verhalten. Sie können eventuell diese Option für die abschließende Erzeugung des fertigen Programms abschalten, um es ein wenig schneller zu machen. Der Unterschied ist jedoch wirklich gering und aus diesem Grund empfehle ich Ihnen, alle diese Laufzeitprüfungen eingeschaltet zu lassen, auch im auszuliefernden Programm. Das selbe gilt auch für andere Optionen zur Laufzeitprüfung, wie Überlaufprüfung und Stack-Kontrolle.

Aufzählungstypen

Aufzählungstypen bilden einen weiteren anwenderdefinierten ordinalen Typ. Anstatt einen Bereich von existierenden Typen anzugeben, listen Sie in einer Aufzählung alle möglichen Werte dieses Typs auf. Mit anderen Worten stellt eine Aufzählung eine Liste von Werten dar. Hier sind einige Beispiele:

type
  Farben = (Rot, Gelb, Gruen, Zyan, Blau, Violett);
  Kartenfarbe = (Karo, Herz, Pik, Kreuz);

Jeder Wert in dieser Liste besitzt eine zugeordnete Ordnungsnummer, beginnend mit Null. Wenn Sie die Ord-Funktion auf einen Werte eines Aufzählungstyps anwenden, so erhalten Sie diesen Null-basierten Wert. Beispielsweise liefert Ord(Herz) den Wert 1.

Hinweis: Aufzählungstypen können eine unterschiedliche interne Darstellung besitzen. Delphi verwendet eine 8-Bit Darstellung, es sei denn es gibt mehr als 256 unterschiedliche Werte. In diesem Fall wird eine 16-Bit Darstellung verwendet. Es gibt auch eine 32-Bit Darstellung, die für die Kompatibilität mit C und C++ Bibliotheken nützlich sein kann. Sie können sogar das voreingestellte Verhalten verändern und um eine größere Darstellung bitten, indem Sie den Compilerschalter $Z verwenden.

Die Delphi-VCL (Visuelle Componentenbibliothek) verwendet Aufzählungstypen an vielen Stellen. Beispielsweise ist der Stil des Rahmens eines Formulars wie folgt definiert:

type
  TFormBorderStyle = (bsNone, bsSingle, bsSizeable,
    bsDialog, bsSizeToolWin, bsToolWindow);

Wenn der Wert einer Eigenschaft eine Aufzählung darstellt, so können Sie diese gewöhnlich aus einer Werteliste auswählen, die im Objektinspektor angezeigt wird. Abbildung 4.1 zeigt die Werteliste.

Abbildung 4.1: Eine Aufzählungstyp-Eigenschaft im Objektinspektor.

In der Delphi-Hilfedatei werden im Allgemeinen die möglichen Werte von Aufzählungen aufgelistet. Als eine Alternative können Sie das Programm OrdType verwenden, welches auf www.marcocantu.com verfügbar ist, um die Liste der Werte für jede Delphi-Aufzählung, Mengen, Teilbereiche und jeden anderen ordinalen Typ anzuzeigen. Sie können ein Beispiel der Ausgabe dieses Programms in Abbildung 4.2 sehen.

Abbildung 4.2: Detaillierte Informationen über einen Aufzählungstyp, wie er durch das Programm OrdType angezeigt wird (verfügbar auf meiner Web-Site).

Mengentypen

Mengentypen kennzeichnen eine Gruppe von Werten, wobei die Liste der verfügbaren Werte durch den ordinalen Typ, auf dem die Menge basiert, bestimmt wird. Dieser ordinale Typ ist gewöhnlich begrenzt und sehr oft durch eine Aufzählung oder einen Teilbereich dargestellt. Wenn wir den Teilbereich 1..3 nehmen, so sind die möglichen Werte der Menge, die darauf basiert, nur 1, nur 2, nur 3, 1 und 2 zusammen, 1 und 3 zusammen, 2 und 3 zusammen, alle drei Werte oder keiner von ihnen.

Eine Variable beinhaltet gewöhnlich nur einen der möglichen Werte aus dem Wertebereich seines Typs. Eine Mengenvariable hingegen kann keinen, einen, zwei, drei oder mehr Werte aus dem Wertebereich beinhalten. Sie kann sogar alle diese Werte beinhalten. Hier folgt ein Beispiel für eine Menge:

type
  Letters = set of Uppercase;

Nun kann ich eine Variable dieses Typs definieren und ihr einige Werte des Basistyps zuweisen. Um einen Mengenwert anzugeben, schreiben Sie eine mit Kommas getrennte Liste, die in eckige Klammern eingeschlossen ist. Der folgende Code zeigt die Zuweisung von mehreren Werten, einem einzelnen Wert und einem leeren Wert an die Variable:

var
  Letters1, Letters2, Letters3: Letters;
begin
  Letters1 := ['A', 'B', 'C'];
  Letters2 := ['K'];
  Letters3 := [];

In Delphi wird eine Menge im Allgemeinen verwendet, um Flags anzuzeigen, die sich nicht gegenseitig ausschließen. Beispielsweise deklarieren die folgenden zwei Code-Zeilen (welche Teil der Delphi-Bibliothek sind) eine Aufzählung der möglichen Icons für den Fensterrahmen und den dazugehörigen Mengentyp:

type
  TBorderIcon = (biSystemMenu, biMinimize, biMaximize, biHelp);
  TBorderIcons = set of TBorderIcon;

Tatsächlich kann ein bestimmtes Fenster keines, ein oder auch mehr als eines dieser Icons besitzen. Wenn Sie mit dem Objektinspektor arbeiten (vergl. Abbildung 4.3) so können Sie die Werte einer Menge einstellen, indem Sie die Auswahl aufklappen (doppelklicken Sie auf den Eigenschaftsnamen oder klicken Sie auf das Pluszeichen auf seiner linken Seite) und schalten Sie die Präsenz für jeden Wert ein oder aus.

Abbildung 4.3: Eine Mengentypeigenschaft im Objektinspektor.

Eine weitere Eigenschaft, die auf einem Mengentyp basiert, ist der Stil einer Schriftart. Die möglichen Werte beschreiben die Schriftart als fett, kursiv, untestrichen und durchgestrichen. Natürlich kann die selbe Schriftart sowohl kursiv als auch fett sein, keine Attribute besitzen oder alle gleichzeitig haben. Aus diesem Grund ist sie als Menge deklariert. Im Code eines Programms können Sie Werte an diese Menge wie folgt zuweisen:

Font.Style := []; // kein Stil
Font.Style := [fsBold]; // nur Stil fett
Font.Style := [fsBold, fsItalic]; // zwei Stilarten

Sie können auch auf verschiedene Weise mit Mengen operieren, einschließlich zwei Variablen des selben Mengentyps addieren (oder um genauer zu sein, die Vereinigungsmenge der beiden Mengenvariablen berechnen):

Font.Style := OldStyle + [fsUnderline]; // zwei Mengen

Wiederum können Sie das Beispiel OrdType verwenden, welches im Verzeichnis TOOLS des Quellcodes zum Buch enthalten ist, um die Liste der möglichen Werte von vielen Mengen anzusehen, die durch die Delphi Komponentenbibliothek definiert sind.

Array-Typen

Array-Typen definieren Listen einer festen Anzahl von Elementen eines bestimmten Typs. Allgemein verwenden Sie einen Index innerhalb von eckigen Klammern, um auf eines der Elemente dieses Arrays zuzugreifen. Die eckigen Klammern werden auch verwendet, um die möglichen Werte des Index zu bestimmen, wenn das Array definiert wird. Beispielsweise können Sie eine Gruppe von 24 Integer-Werten mit diesem Code vereinbaren:

type
  DayTemperatures = array [1..24] of Integer;

In der Array-Vereinbarung müssen Sie innerhalb der eckigen Klammern einen Teilbereichstyp angeben oder einen neuen spezifischen Teilbereichstyp definieren, indem zwei Konstanten eines ordinalen Typs angegeben werden. Dieser Teilbereich bestimmt die gültigen Indizes dieses Arrays. Da Sie sowohl den größten als auch den kleinsten Index des Arrays bestimmen muß der Index nicht Null-basiert sein, wie es in C, C++, Java und anderen Programmiersprachen notwendig ist.

Da die Array-Indizes auf einem Teilbereich basieren, kann Delphi diesen Bereich prüfen, wie wir es bereits gesehen haben. Ein ungültiger konstanter Teilbereichswert führt zu einem Entwurfszeitfehler, und die Verwendung eines Indizes außerhalb des zulässigen Bereichs während der Programmausführung führt zu einem Laufzeitfehler, wenn die entsprechende Compiler-Option gesetzt ist.

Unter Verwendung der obigen Array-Deklaration können Sie den Wert der Variable DayTemp1 vom Typ DayTemperatures wie folgt zuweisen:

type
  DayTemperatures = array [1..24] of Integer;

var  
  DayTemp1: DayTemperatures;
  
procedure AssignTemp;  
begin  
  DayTemp1 [1] := 54;
  DayTemp1 [2] := 52;
  ...
  DayTemp1 [24] := 66;
  DayTemp1 [25] := 67; // Entwurfszeitfehler

Ein Array kann mehr als eine Dimension besitzen, wie im folgenden Beispiel:

type
  MonthTemps = array [1..24, 1..31] of Integer;
  YearTemps = array [1..24, 1..31, Jan..Dec] of Integer;

Diese zwei Array-Typen bauen auf den selben Kerntypen auf. Daher können Sie diese auch unter Verwendung der vorhergehenden Datentypen deklarieren, wie es der folgende Code zeigt:

type
  MonthTemps = array [1..31] of DayTemperatures;
  YearTemps = array [Jan..Dec] of MonthTemps;

Diese Deklaration kehrt die Reihenfolge der Indizes gegenüber den zuerst vorgestellten Arrays um, aber sie gestattet nun die Zuweisung von ganzen Blöcken zwischen den Variablen. Beispielsweise kopiert die folgende Anweisung die Januartemperaturen in den Februar:

var
  ThisYear: YearTemps;
begin
  ...
  ThisYear[Feb] := ThisYear[Jan];

Sie können auch ein Null-basiertes Array definieren, ein Array-Typ bei dem die untere Grenze auf Null gesetzt ist. Allgemein ist die Verwendung von verständlicheren Grenzen ein Vorteil, da Sie nicht den Index 2 benutzen müssen, um auf das dritte Element zuzugreifen usw. Windows hingegen verwendet unveränderlich Null-basierte Arrays (da es auf der Sprache C basiert) und die Delphi Componentenbibliothek neigt dazu, das gleiche zu tun.

Wenn Sie mit einem Array arbeiten müssen, können Sie stets seine Grenzen unter Verwendung der Standardfunktionen Low und High überprüfen, welche die untere und obere Grenze zurückliefern. Die Verwendung von Low und High bei der Arbeit mit Arrays ist äußerst empfehlenswert, besonders in Schleifen, da dies den Code unabhängig von der Größe des Arrays macht. Später können Sie den deklarierten Bereich der Array-Indizes ändern und der Code, der Low und High verwendet wird dennoch funktionieren. Wenn Sie in einer Schleife den Bereich eines Arrays fest codieren, so müssen Sie den Code der Schleife überarbeiten, wenn sie die Array-Größe verändern. Low und High bewirken, dass Ihr Code zuverlässiger und einfacher zu warten sein wird.

Hinweis: Nebenbei bemerkt, gibt es keine zusätzliche Belastung der Laufzeit, wenn Sie Low und High mit Arrays verwenden. Diese werden zur Übersetzungszeit in Konstanten aufgelöst und sind keine echten Funktionsaufrufe. Diese Übersetzungszeitauflösung von Ausdrücken und Funktionsaufrufen erfolgt auch für viele andere einfache Systemfunktionen.

Delphi verwendet Arrays hauptsächlich in der Form von Array-Eigenschaften. Wir haben dazu bereits ein Beispiel solch einer Eigenschaft im Programm TimeNow gesehen, um auf die Eigenschaft Items eines Listenfelds zuzugreifen. Im nächsten Kapitel werde ich Ihnen einige weitere Beispiele für Array-Eigenschaften zeigen, wenn wir Schleifen in Delphi besprechen.

Hinweis: Delphi 4 führte dynamische Arrays in Objekt Pascal ein, dies sind Arrays, die zur Laufzeit in ihrer Größe verändert werden können und dabei die korrekte Speichergröße zugewiesen bekommen. Die Verwendung von dynamischen Arrays ist einfach, aber ich glaube, dass sie in dieser Diskussion von Pascal nicht das geeignete Thema sind. Eine Beschreibung von Delphi's dynamischen Arrays können Sie im Kapitel 8 finden.

Record-Typen

Record-Typen vereinbaren eine feste Zusammenfassung von Elementen unterschiedlichen Typs. Jedes Element, oder Feld, hat seinen eigenen Typ. Die Deklaration eines Record-Typs listet alle diese Felder auf und gibt jedem einen Namen, den Sie später verwenden werden, um darauf zuzugreifen.

Hier ist ein kleiner Programmausschnitt mit der Definition eines Record-Typs, der Deklaration einer Variable diesen Typs und ein paar Anweisungen, um diese Variable zu verwenden:

type
  Date = record
    Year: Integer;
    Month: Byte;
    Day: Byte;
  end;
  
var
  BirthDay: Date;
  
begin
  BirthDay.Year := 1997;
  BirthDay.Month := 2;
  BirthDay.Day := 14;

Klassen und Objekte können als Erweiterung des Record-Typs aufgefasst werden. Die Delphi-Bibliotheken neigen dazu, Klassentypen anstelle von Record-Typen zu verwenden, es sind aber viele Record-Typen durch das Windows API definiert.

Record-Typen können auch einen varianten Teil besitzen; d.h. mehrere Felder können auf den selben Speicherbereich abgebildet werden, auch wenn Sie einen unterschiedlichen Datentyp besitzen. (Das entspricht einer Union in der Sprache C.) Wahlweise können Sie diese Variant-Felder oder Gruppen von Feldern benutzen, um auf den selben Speicherort innerhalb des Records zuzugreifen, wobei Sie diese Werte aus unterschiedlichen Perspektiven betrachten können. Die hauptsächliche Verwendung dieses Typs war es, ähnliche aber unterschiedliche Daten zu Speichern und einen ähnlichen Effekt wie die Typumwandlung zu erzielen (etwas was jetzt wenig nützlich ist, da Typumwandlung ebenfalls in Pascal eingeführt wurde). Die Verwendung von varianten Record-Typen wurde weitgehend durch die Objektorientierung und andere moderne Techniken ersetzt, obwohl Delphi diese in einigen besonderen Fällen verwendet.

Die Verwendung von varianten Records ist nicht typsicher und ist keine empfehlenswerte Programmierpraxis, besonders für Anfänger. Programmierexperten können jedoch variante Record-Typen verwenden, und der Kern der Delphi-Bibliotheken verwendet sie auch. Sie werden sie nicht anpacken müssen bis Sie wirklich ein Delphi Experte sind, wenn überhaupt.

Zeiger

Ein Zeigertyp definiert eine Variable, die die Speicheradresse einer anderen Variablen mit einem bestimmten Datentyp (oder einem undefinierten Typ) beinhaltet. Damit verweist ein Zeigervariable indirekt auf einen Wert. Die Definition eines Zeigertyps beruht auf keinem besonderen Schlüsselwort sondern verwendet statt dessen ein besonderes Zeichen. Dieses besondere Zeichen ist das Caret (^) auch als Einschaltungszeichen bezeichnet:

type
  PointerToInt = ^Integer;

Wenn Sie eine Zeigervariable definiert haben, so können Sie ihr die Adresse einer anderen Variablen des selben Typs unter Verwendung des @ Operators zuweisen:

var
  P: ^Integer;
  X: Integer;
begin
  P := @X;
  // Änderung des Wertes auf zwei unterschiedlichen Wegen
  X := 10;
  P^ := 20;  

Wenn Sie einen Zeiger P vorliegen haben, so beziehen Sie sich mit dem Ausdruck P auf die Adresse der Speicherstelle, auf die der Zeiger verweist und mit dem Ausdruck P^ beziehen Sie sich auf den aktuellen Inhalt der Speicherstelle. Aus diesem Grund verweist dar Codeausschnitt P^ auf X.

Anstatt auf eine existierende Speicherstelle zu verweisen, kann ein Zeiger auch auf einen neuen Speicherblock verweisen, der dynamisch mit der Prozedur New (im Speicherbereich des Heap) zugeteilt wurde. In diesem Fall müssen Sie den Speicher wieder freigeben, wenn Sie den Zeiger nicht mehr benötigen, indem Sie die Prozedur Dispose aufrufen.

var
  P: ^Integer;
begin
  // Initialisierung
  New (P);
  // Operationen
  P^ := 20;
  ShowMessage (IntToStr (P^));
  // Freigabe
  Dispose (P);
end;

Wenn ein Zeiger keinen Wert hat, so können Sie ihm den Wert nil zuweisen. Damit können Sie testen, ob ein Zeiger nil ist, um zu sehen ob er momentan auf einen Wert verweist. Dies wird häufig benötigt, da die Dereferenzierung eines ungültigen Zeigers eine Zugriffsverletzung (auch bekannt als allgemeine Schutzverletzung, GPF - general protection fault) bewirkt:

procedure TFormGPF.BtnGpfClick(Sender: TObject);
var
  P: ^Integer;
begin
  P := nil;
  ShowMessage (IntToStr (P^));
end;

Sie können ein Beispiel für die Auswirkung dieses Programmcodes sehen, indem Sie das Beispiel GPF starten (oder sich die entsprechende Abbildung 4.4 ansehen). Das Beispiel enthält auch die oben gezeigten Codeabschnitte.

Abbildung 4.4: Der Systemfehler, der aus dem Zugriff auf einen nil-Zeiger resultiert, verursacht durch das GPF-Beispiel.

Im selben Programm können Sie ein Beispiel für einen sicheren Datenzugriff finden. In diesem zweiten Fall verweist der Zeiger auf eine existierende lokale Variable und kann sicher verwendet werden. Ich habe aber dennoch eine Sicherheitskontrolle eingebaut:

procedure TFormGPF.BtnSafeClick(Sender: TObject);
var
  P: ^Integer;
  X: Integer;
begin
  P := @X;
  X := 100;
  if P <> nil then
    ShowMessage (IntToStr (P^));
end;

Delphi definiert auch einen Datentyp Pointer, welcher einen untypisierten Zeiger kennzeichnet (ähnlich wie void* in der Sprache C). Wenn Sie einen untypisierten Zeiger verwenden, so sollten Sie GetMem anstelle von New verwenden. Die Prozedur GetMem ist jedes mal dann erforderlich, wenn die Speichergröße der zuzuweisenden Variable nicht definiert ist.

Die Tatsache, dass Zeiger in Delphi selten erforderlich sind, ist ein interessanter Vorteil dieser Entwicklungsumgebung. Dennoch ist ein Verständnis von Zeigern für die fortgeschrittene Programmierung wichtig und sie dient dem vollständigen Verständnis des Delphi Objektmodells, welches Zeiger "hinter den Kulissen" verwendet.

Hinweis: Obwohl Sie in Delphi selten Zeiger verwenden werden, so werden Sie sehr oft einen ähnlichen Konstrukt benutzen - nämlich Referenzen. Jede Objektinstanz ist tatsächlich ein impliziter Zeiger bzw. eine Referenz auf die aktuellen Daten. Dies ist jedoch für den Programmierer vollständig transparent, da er Objektvariablen genauso wie alle anderen Datentypen verwendet.

File-Typen

Ein weiterer Pascal-spezifischer Typkonstrukt ist der File-Typ (Dateityp). File-Typen repräsentieren physikalische Dateien auf Laufwerken, mit Sicherheit eine Besonderheit der Sprache Pascal. Sie können einen File-Datentyp wie folgt definieren:

type
  IntFile = file of Integer;

Dann können Sie eine physikalische Datei verwenden, die mit dieser Struktur verknüpft wird, und Integer-Werte dort hineinschreiben oder den aktuellen Wert aus der Datei lesen.

Anmerkung des Autors: Dateibasierte Beispiele waren Teil der älteren Ausgaben von Mastering Delphi und ich plane, diese hier ebenfalls einzufügen.

Die Verwendung von Dateien in Pascal ist ziemlich unkompliziert, aber in Delphi existieren ebenfalls einige Komponenten, die in der Lage sind, ihren Inhalt in oder aus einer Datei zu laden. Weiterhin gibt es einige Unterstützung für die Serialisierung in Form von Streams, und zusätzlich existiert die Datenbankunterstützung.

Zusammenfassung

Dieses Kapitel behandelt anwenderdefinierte Datentypen und vervollständigt unser Wissen über das Pascal Typsystem. Nun sind wir in der Lage uns den Anweisungen zuzuwenden, die die Sprache bereitstellt, um mit den Variablen zu arbeiten, die wir definiert haben.

Nächstes Kapitel: Anweisungen

© Copyright Marco Cantù, Wintech Italia Srl 1995-2000
© Copyright der deutschen Übersetzung Immo Wache, 2000