Strukturierte Typen (Object Pascal)

Aus Appmethod Topics
Wechseln zu: Navigation, Suche

Nach oben zu Datentypen, Variablen und Konstanten - Index


Die Instanzen eines strukturierten Typs enthalten mehrere Werte. Zu den strukturierten Typen gehören Mengen-, Array-, Record- und Datei-, Klassen-, Klassenreferenz- und Interface-Typen. Mit Ausnahme von Mengen, die nur ordinale Werte enthalten, können strukturierte Typen auch andere strukturierte Typen beinhalten. Ein Typ kann beliebig viele strukturelle Ebenen umfassen.

Dieses Thema enthält Informationen zu folgenden strukturierten Typen:

  • Mengentypen
  • Array-Typen (statisch und dynamisch)
  • Record-Typen
  • Dateitypen

Ausrichtung von strukturierten Typen

Per Voreinstellung sind die Werte in einem strukturierten Typ zur Beschleunigung des Zugriffs an einem Word- oder Double-Word-Raster ausgerichtet.

Sie können aber die Byte-Ausrichtung beim Deklarieren eines strukturierten Typs durch Angabe des reservierten Wortes packed festlegen. Das Wort packed legt die Datenspeicherung in komprimierter Form fest. Dazu eine Beispieldeklaration:

 type TNumbers = packed array [1..100] of Real;

Die Verwendung von packed wird nicht empfohlen, da es die Kompatibilität mit anderen Sprachen oder Plattformen verhindern kann, den Datenzugriff verlangsamt und sich bei Zeichen-Arrays auf die Typkompatibilität auswirkt. Weitere Informationen dazu finden Sie unter Speicherverwaltung und Implizites Packen von Feldern mit einer gemeinsamen Typspezifikation.

Mengentypen

Eine Menge setzt sich aus mehreren Werten desselben ordinalen Typs zusammen. Die Werte haben keine feste Reihenfolge. Wenn ein Wert in einer Menge doppelt vorkommt, hat jedes Vorkommen dieselbe Bedeutung.

Der Bereich eines Mengentyps ist die Potenzmenge eines bestimmten Ordinaltyps, der als Basistyp bezeichnet wird. Die möglichen Werte eines Mengentyps sind Teilmengen des Basistyps, einschließlich der leeren Menge. Der Basistyp darf aus maximal 256 Werten bestehen. Die Ordinalpositionen der Werte müssen zwischen 0 und 255 liegen. Alle Konstruktionen der Form:

set of Basistyp

bezeichnen einen Mengentyp. Dabei ist Basistyp ein entsprechender ordinaler Typ.

Aufgrund der Größenbeschränkung von Basistypen werden Mengentypen normalerweise mit Teilmengen definiert. So lässt sich mit den Deklarationen

 type
   TSomeInts = 1..250;
   TIntSet = set of TSomeInts;

ein Mengentyp namens TIntSet erstellen, dessen Werte Integer-Zahlen im Bereich zwischen 1 und 250 sind. Sie können dazu auch folgende Anweisung verwenden:

 type TIntSet = set of 1..250;

Mit dieser Deklaration können Sie beispielsweise folgende Mengen erstellen:

 var Set1, Set2: TIntSet;
   ...
 Set1 := [1, 3, 5, 7, 9];
 Set2 := [2, 4, 6, 8, 10]

Die Konstruktion set of ... kann direkt in Variablendeklarationen verwendet werden:

 var MySet: set of 'a'..'z';
   ...
 MySet := ['a','b','c'];

Hier einige weitere Beispiele für Mengentypen:

 set of Byte;
 set of (Club, Diamond, Heart, Spade);
 set of Char;

Der Operator in überprüft, ob ein Element zu einer Menge gehört:

 if 'a' in MySet then ... { do something } ;

Jeder Mengentyp kann die leere Menge enthalten, die mit [] gekennzeichnet wird. Weitere Informationen zu Mengen finden Sie in den Abschnitten "Mengen-Konstruktoren" und "Mengen-Operatoren" unter Ausdrücke (Object Pascal).

Array-Typen

Ein Array ist eine indizierte Menge von Elementen desselben Typs (des so genannten Basistyps). Da jedes Element einen eindeutigen Index hat, kann ein Array (im Gegensatz zu einer Menge) denselben Wert mehrmals und mit unterschiedlicher Bedeutung enthalten. Arrays können statisch oder dynamisch zugewiesen werden.

Statische Arrays

Statische Array-Typen werden mit der folgenden Konstruktion definiert:

array[Indextyp1, ..., Indextypn] of Basistyp;

Indextyp ist immer ein ordinaler Typ, dessen Bereich 2 GB nicht überschreitet. Da das Array über den Indextyp indiziert wird, ist die Anzahl der Elemente durch den angegebenen Indextyp beschränkt. In der Praxis sind die Indextypen normalerweise Integer-Teilbereiche.

Im einfachsten Fall eines eindimensionalen Arrays ist nur ein einziger Indextyp vorhanden. Beispiel:

 var MyArray: array [1..100] of Char;

Hier wird eine Variable namens MyArray deklariert, die 100 Zeichenwerte enthält. Aufgrund dieser Deklaration bezeichnet MyArray[3] das dritte Zeichen in MyArray. Wenn Sie ein statisches Array erstellen und nicht allen Elementen Werte zuweisen, werden die unbenutzten Elemente dennoch vergeben. Diese Elemente enthalten zu Beginn zufällige Daten und sind mit nicht initialisierten Variablen vergleichbar.

Ein mehrdimensionales Array ist ein Array, das andere Arrays enthält. Zum Beispiel ist die Anweisung:

 type TMatrix = array[1..10] of array[1..50] of Real;

gleichbedeutend mit:

 type TMatrix = array[1..10, 1..50] of Real;

Unabhängig von der Art der Deklaration repräsentiert TMatrix immer ein Array mit 500 reellen Werten. Eine Variable namens MyMatrix vom Typ TMatrix kann auf zwei Arten indiziert werden: MyMatrix[2,45]; oder wie folgt: MyMatrix[2][45]. Genauso ist

 packed array[Boolean, 1..10, TShoeSize] of Integer;

gleichbedeutend mit:

 packed array[Boolean] of packed array[1..10] of packed array[TShoeSize] of Integer;

Die Standardfunktionen Low und High können für Array-Typbezeichner und Variablen angewendet werden. Sie liefern die untere und obere Grenze des ersten Indextyps im Array. Die Standardfunktion Length gibt die Anzahl der Elemente in der ersten Dimension des Arrays zurück.

Ein eindimensionales, gepacktes statisches Array mit Char-Werten wird als gepackter String bezeichnet. Gepackte String-Typen sind mit String-Typen und anderen gepackten String-Typen kompatibel, die dieselbe Anzahl von Elementen haben. Weitere Informationen finden Sie unter Kompatibilität und Identität von Typen.

Ein Array der Form array[0..x] of Char wird als nullbasiertes Zeichen-Array bezeichnet, da sein Index bei 0 beginnt. Nullbasierte Zeichen-Arrays werden zum Speichern von nullterminierten Strings verwendet und sind kompatibel mit PChar-Werten. Informationen hierzu finden Sie im Abschnitt "Nullterminierte Strings" unter String-Typen (Object Pascal).

Dynamische Arrays

Dynamische Arrays haben keine feste Größe oder Länge. Der Speicher für ein dynamisches Array wird reserviert, sobald Sie dem Array ein Wert zuweisen oder es an die Prozedur SetLength übergeben. Dynamische Array-Typen werden folgendermaßen deklariert:

array of Basistyp

Zum Beispiel deklariert die Anweisung:

 var MyFlexibleArray: array of Real;

ein eindimensionales Array mit Elementen vom Typ Real. Diese Deklaration weist MyFlexibleArray keinen Speicherplatz zu. Um ein Array im Speicher anzulegen, rufen Sie SetLength auf. Nach der vorherigen Typdeklaration weist

 SetLength(MyFlexibleArray, 20);

ein Array mit 20 reellen Zahlen und einem Index von 0 bis 19 zu. Das Aufrufen des Array-Konstruktors stellt eine alternative Methode für die Zuweisung von Speicher für dynamische Arrays dar:

 type
   TMyFlexibleArray = array of Integer;

 begin
   MyFlexibleArray := TMyFlexibleArray.Create(1, 2, 3 {...});
 end;

Diese Anweisung weist Speicher für drei Elemente zu und ordnet jedem Element den angegebenen Wert zu.

Dynamische Arrays haben immer einen ganzzahligen Index, der stets mit 0 beginnt.

Dynamische Array-Variablen sind implizit Zeiger und werden mit derselben Referenzzählung verwaltet wie lange Strings. Um ein dynamisches Array freizugeben, weisen Sie einer Variable, die das Array referenziert, den Wert nil zu, oder Sie übergeben die Variable an Finalize. Beide Methoden geben das Array unter der Voraussetzung frei, dass keine weiteren Referenzen darauf vorhanden sind. Dynamische Arrays werden immer freigegeben, sobald ihr Referenzzähler null ist. Dynamische Arrays der Länge 0 haben immer den Wert nil. Verwenden Sie für dynamische Array-Variablen nicht den Derefenzierungsoperator (^), und übergeben Sie sie auch nicht an die Prozeduren New oder Dispose.

Wenn X und Y Variablen desselben dynamischen Array-Typs sind, führt die Anweisung X := Y dazu, dass X auf dasselbe Array wie Y zeigt. (Es ist nicht erforderlich, vor dieser Operation Speicher für X zu reservieren.) Im Gegensatz zu Strings und statischen Arrays wird copy-on-write nicht für dynamische Arrays verwendet. Deshalb werden diese nicht automatisch kopiert, bevor einem ihrer Elemente ein Wert zugewiesen wird. Beispielsweise hat A[0] nach der Ausführung des folgenden Quelltextes den Wert 2:

 var
   A, B: array of Integer;
   begin
     SetLength(A, 1);
     A[0] := 1;
     B := A;
     B[0] := 2;
   end;

(Wenn A und B statische Arrays wären, hätte A[0] immer noch den Wert 1.)

Durch Zuweisungen an ein dynamisches Array über den Index (wie beispielsweise MyFlexibleArray[2] := 7) wird für das Array kein neuer Speicherplatz reserviert. Der Compiler akzeptiert auch Indizes, die außerhalb des angegebenen Bereichs liegen.

Wenn Sie im Gegensatz dazu eine unabhängige Kopie eines dynamischen Arrays erstellen möchten, müssen Sie die globale Funktion Copy verwenden:

 var
   A, B: array of Integer;
 begin
   SetLength(A, 1);
   A[0] := 1;
   B := Copy(A);
   B[0] := 2; { B[0] <> A[0] }
 end;

Bei einem Vergleich von dynamischen Array-Variablen werden nicht die Array-Werte, sondern die Referenzen verglichen. Deshalb liefert A = B nach Ausführung des Quelltextes

 var
   A, B: array of Integer;
 begin
    SetLength(A, 1);
    SetLength(B, 1);
    A[0] := 2;
    B[0] := 2;
 end;

den Wert False, während A[0] = B[0]True zurückgibt.

Um ein dynamisches Array abzuschneiden, übergeben Sie es an SetLength oder Copy und weisen das Ergebnis wieder der Array-Variable zu. (Die Prozedur SetLength ist normalerweise schneller.) Wenn A beispielsweise ein dynamisches Array ist, können Sie mit folgenden Anweisungen die ersten 20 Elemente von A beibehalten, und den Rest abschneiden:

 SetLength(A, 20)
 A := Copy(A, 0, 20)

Sobald einem dynamischen Array Speicherplatz zugewiesen wurde, kann es an die Standardfunktionen Length, High und Low übergeben werden. Length liefert die Anzahl der Elemente im Array, High den höchsten Index des Arrays (Length - 1) und Low den Wert 0. Bei einem Array mit der Länge Null liefert High das Ergebnis -1 (mit der unsinnigen Folge, dass High kleiner als Low ist).

Hinweis: In einigen Funktions- und Prozedurdeklarationen werden Array-Parameter in der Form array of Basistyp ohne definierten Indextyp angegeben. Zum Beispiel: function CheckStrings(A: array of string): Boolean;

In diesem Fall kann die Funktion für alle Arrays des angegebenen Basistyps angewendet werden, unabhängig von der Größe der Arrays und der Art ihrer Indizierung. Es spielt auch keine Rolle, ob den Arrays der Speicherplatz statisch oder dynamisch zugewiesen wird.

Mehrdimensionale dynamische Arrays

Zur Deklaration von mehrdimensionalen dynamischen Arrays verwenden Sie aufeinander folgende array of ...-Konstruktionen. Beispiel:

 type TMessageGrid = array of array of string;
 var Msgs: TMessageGrid;

Hier wird ein zweidimensionales String-Array deklariert. Um dieses Array zu instantiieren, rufen Sie SetLength mit zwei Integer-Argumenten auf. Wenn beispielsweise I und J Integer-Variablen sind, wird Speicherplatz für ein I mal J großes Array zugewiesen:

 SetLength(Msgs,I,J);

Msgs[0,0] bezeichnet dann ein Element dieses Arrays.

Sie können auch mehrdimensionale dynamische Arrays anlegen, die nicht gleichförmig sind. Rufen Sie dazu zunächst die Funktion SetLength auf, und übergeben Sie ihr Parameter für die ersten n Dimensionen des Arrays. Beispiel:

 var Ints: array of array of Integer;
 SetLength(Ints,10);

Mit dieser Anweisung weisen Sie dem Array Ints Speicherplatz für zehn Zeilen zu. Den Speicher für die Spalten können Sie später einzeln zuweisen (und dabei unterschiedliche Längen angeben):

 SetLength(Ints[2], 5);

Die dritte Spalte von Ints kann damit fünf Integer-Werte aufnehmen, und Sie können ihr nun Werte zuweisen (auch wenn die anderen Spalten nicht zugewiesen sind), z.B. Ints[2,4] := 6.

Im folgenden Beispiel wird mithilfe von dynamischen Arrays (und der in der Unit SysUtils deklarierten Funktion IntToStr) eine ungleichförmige String-Matrix erstellt.

 var
   A : array of array of string;
   I, J : Integer;
 begin
   SetLength(A, 10);
   for I := Low(A) to High(A) do
   begin
     SetLength(A[I], I);
     for J := Low(A[I]) to High(A[I]) do
       A[I,J] := IntToStr(I) + ',' + IntToStr(J) + ' ';
     end;
   end;

Array-Typen und Zuweisungen

Arrays sind nur dann zuweisungskompatibel, wenn sie denselben Typ haben. Da Object Pascal Namensäquivalente für Typen verwendet, wird folgender Quelltext nicht compiliert.

 var
   Int1: array[1..10] of Integer;
   Int2: array[1..10] of Integer;
       ...
   Int1 := Int2;

Damit die Zuweisung korrekt bearbeitet werden kann, deklarieren Sie die Variablen folgendermaßen:

 var Int1, Int2: array[1..10] of Integer;

oder:

 type IntArray = array[1..10] of Integer;
 var
    Int1: IntArray;
    Int2: IntArray;

Records (traditionelle)

Ein Record (in einigen Programmiersprachen auch als Struktur bezeichnet) stellt eine heterogene Menge von Elementen dar. Die Elemente werden Felder genannt. In der Deklaration eines Record-Typs wird für jedes Feld ein Name und ein Typ festgelegt. Die Syntax für die Deklaration eines Record-Typs lautet:

 type recordTypeName = record
   fieldList1: type1;
    ...
   fieldListn: typen;
 end

recordTypeName ist ein gültiger Bezeichner, type gibt einen Typ an, und fieldList ist ein gültiger Bezeichner oder eine Liste von Bezeichnern, die durch Kommas voneinander getrennt sind. Der letzte Strichpunkt ist optional.

Die folgende Deklaration legt einen Record-Typ namens TDateRec an.

 type
   TDateRec = record
     Year: Integer;
     Month: (Jan, Feb, Mar, Apr, May, Jun,
             Jul, Aug, Sep, Oct, Nov, Dec);
     Day: 1..31;
   end;

Jeder TDateRec-Record enthält drei Felder: einen Integer-Wert namens Year, einen Aufzählungswert namens Month und einen weiteren Integer-Wert zwischen 1 und 31 namens Day. Die Bezeichner Year, Month und Day sind Feldbezeichner für TDateRec und verhalten sich wie Variablen. Die Typdeklaration für TDateRec weist den Feldern Year, Month und Day aber keinen Speicherplatz zu. Die Reservierung des Speichers erfolgt erst, wenn der Record instantiiert wird:

 var Record1, Record2: TDateRec;

Diese Variablendeklaration erzeugt zwei Instanzen von TDateRec namens Record1 und Record2.

Sie können auf die Felder eines Records zugreifen, indem Sie die Feldbezeichner mit dem Record-Namen qualifizieren:

 Record1.Year := 1904;
 Record1.Month := Jun;
 Record1.Day := 16;

Alternativ dazu ist auch die Verwendung einer with-Anweisung möglich:

 with Record1 do
 begin
   Year := 1904;
   Month := Jun;
   Day := 16;
 end;

Nun können die Werte der Felder von Record1 nach Record2 kopiert werden:

 Record2 := Record1;

Da der Gültigkeitsbereich eines Feldbezeichners auf den Record beschränkt ist, in dem er sich befindet, brauchen Sie nicht auf eventuelle Namenskonflikte zwischen Feldbezeichnern und anderen Variablen zu achten.

Statt der Definition von Record-Typen kann die Konstruktion record ... auch direkt in Variablendeklarationen verwendet werden:

 var S: record
   Name: string;
   Age: Integer;
 end;

Eine solche Deklaration macht aber wenig Sinn, da der eigentliche Zweck eines Records darin besteht, die wiederholte Deklaration ähnlicher Variablengruppen zu vermeiden. Außerdem sind separat deklarierte Records auch dann nicht zuweisungskompatibel, wenn ihre Strukturen identisch sind.

Variante Teile in Record-Typen

Ein Record-Typ kann einen varianten Teil enthalten, der einer case-Anweisung ähnelt. Dieser variante Teil muss in der Typdeklaration nach den Feldern angegeben werden.

Mit der folgenden Syntax deklarieren Sie einen Record-Typ mit einem varianten Teil:

 type recordTypeName = record
   fieldList1: type1;
    ...
   fieldListn: typen;
 case tag: ordinalType of
   constantList1: (variant1);
    ...
   constantListn: (variantn);
 end;

Der erste Teil der Deklaration (bis zum reservierten Wort case) ist identisch mit der Deklaration eines Standard-Records. Der Rest der Deklaration (von case bis zum abschließenden optionalen Strichpunkt) stellt den varianten Teil mit folgenden Komponenten dar. Im varianten Teil

  • Ist tag optional und kann ein beliebiger, gültiger Bezeichner sein. Wenn Sie tag weglassen, entfällt auch der Doppelpunkt (:).
  • Bezeichnet ordinalType einen ordinalen Typ.
  • Ist jede constantList eine Konstante (oder eine Liste von Konstanten, die durch Kommas voneinander getrennt sind), die einen Wert des Typs ordinalType bezeichnet. In den constantLists darf jeder Wert nur einmal vorkommen.
  • Ist variant eine Liste mit Deklarationen, die durch Strichpunkte voneinander getrennt sind. Die Liste ähnelt in etwa den fieldList: type-Konstruktionen im Hauptteil des Record-Typs. Eine Variante hat demnach folgende Form:
 fieldList1: type1;
   ...
 fieldListn: typen;

Dabei ist fieldList ein gültiger Bezeichner oder eine Liste von Bezeichnern, die durch Kommas voneinander getrennt sind. type ist ein Typ. Der letzte Strichpunkt ist optional. Bei type darf es sich nicht um einen langen String, ein dynamisches Array, eine Variante (Typ Variant) oder ein Interface handeln. Strukturierte Typen, die lange Strings, dynamische Arrays, Varianten oder Interfaces enthalten, sind ebenfalls nicht zulässig. Zeiger auf diese Typen dürfen jedoch verwendet werden.

Die Syntax für Records mit varianten Teilen ist kompliziert, ihre Semantik ist jedoch einfach. Der variante Teil eines Records enthält mehrere Varianten, die sich denselben Speicherplatz teilen. Auf die Felder einer Variante kann jederzeit ein Lese- oder Schreibzugriff erfolgen. Wenn Sie allerdings zunächst in ein Feld einer Variante schreiben und anschließend in ein Feld einer anderen Variante, kann das zum Überschreiben der eigenen Daten führen. Falls vorhanden, agiert tag als gesondertes Feld (des Typs ordinalType) im nicht varianten Teil des Records.

Variante Teile erfüllen zwei Funktionen, die sich am besten anhand eines Beispiels verdeutlichen lassen. Angenommen, Sie möchten einen Record-Typ erstellen, der Felder für unterschiedliche Daten enthält. Sie wissen, dass Sie nie alle Felder einer einzelnen Record-Instanz benötigen werden. Beispiel:

 type
   TEmployee = record
   FirstName, LastName: string[40];
   BirthDate: TDate;
   case Salaried: Boolean of
     True: (AnnualSalary: Currency);
     False: (HourlyWage: Currency);
 end;

Diesem Beispiel liegt die Überlegung zugrunde, dass ein Angestellter entweder ein jährliches Festgehalt (AnnualSalary) oder einen Stundenlohn (HourlyWage) erhält, und dass für einen Angestellten immer nur eine der Zahlungsarten in Frage kommt. Wenn Sie eine Instanz von TEmployee anlegen, muss also nicht für beide Felder Speicherplatz reserviert werden. In diesem Beispiel unterscheiden sich die Varianten nur durch die Feldnamen. Die Felder könnten aber auch unterschiedliche Typen haben. Hier einige komplexere Beispiele:

 type
   TPerson = record
   FirstName, LastName: string[40];
   BirthDate: TDate;
   case Citizen: Boolean of
     True: (Birthplace: string[40]);
     False: (Country: string[20];
             EntryPort: string[20];
             EntryDate, ExitDate: TDate);
   end;

 type
   TShapeList = (Rectangle, Triangle, Circle, Ellipse, Other);
   TFigure = record
     case TShapeList of
       Rectangle: (Height, Width: Real);
       Triangle: (Side1, Side2, Angle: Real);
       Circle: (Radius: Real);
       Ellipse, Other: ();
   end;

Der Compiler weist jeder Record-Instanz so viel Speicherplatz zu, wie die Felder in der größten Variante benötigen. Die optionalen Komponenten tag und constantLists (wie Rectangle, Triangle usw. im letzten Beispiel) spielen für die Art und Weise, wie der Compiler die Felder verwaltet, keine Rolle. Sie erleichtern lediglich die Arbeit des Programmierers.

Wie bereits erwähnt, erfüllen variante Teile noch eine zweite Aufgabe. Sie können dieselben Daten so behandeln, als würden sie zu unterschiedlichen Typen gehören. Wenn beispielsweise das erste Feld einer Variante einen 64-Bit-Real-Wert und das erste Feld einer anderen Variante einen 32-Bit-Integer-Wert enthält, können Sie dem Real-Feld einen Wert zuweisen und anschließend die ersten 32 Bit davon als Wert des Integer-Feldes auslesen (und sie beispielsweise an eine Funktion übergeben, die Integer-Parameter erwartet).

Records (erweiterte)

Zusätzlich zu den herkömmlichen Record-Typen lässt die Object Pascal-Sprache komplexere und "klassenähnliche" Record-Typen zu. Zusätzlich zu Feldern können Records Eigenschaften und Methoden (einschließlich Konstruktoren), Klasseneigenschaften, Klassenmethoden, Klassenfelder und verschachtelte Typen haben. Weitere Informationen hierzu finden Sie in der Dokumentation für Klassen und Objekte. Das Folgende ist eine Beispiel-Record-Typdefinition mit einigen "klassenähnlichen" Merkmalen.

 type
   TMyRecord = record
     type
       TInnerColorType = Integer;
     var
       Red: Integer;
     class var
       Blue: Integer;
     procedure printRed();
     constructor Create(val: Integer);
     property RedProperty: TInnerColorType read Red write Red;
     class property BlueProp: TInnerColorType read Blue write Blue;
 end;

 constructor TMyRecord.Create(val: Integer);
 begin
   Red := val;
 end;

 procedure TMyRecord.printRed;
 begin
   Writeln('Red: ', Red);
 end;

Records besitzen nun einige der Merkmale von Klassen, aber gibt es wichtige Unterschiede zwischen Klassen und Records.

  • Records unterstützen keine Vererbung.
  • Records können variante Teile enthalten; Klassen nicht.
  • Records sind Wertetypen, daher werden Sie bei der Zuweisung kopiert, per Wert übergeben und dem Stack zugewiesen, wenn sie nicht als global definiert sind oder explizit mit den Funktionen New und Dispose zugewiesen werden. Klassen sind Referenztypen, daher werden Sie bei der Zuweisung nicht kopiert, per Referenz übergeben und dem Heap zugewiesen.
  • Records ermöglichen das Überladen von Operatoren auf Win32-Plattformen; Klassen ermöglichen kein Überladen von Operatoren.
  • Records werden automatisch mit einem Standardkonstruktor ohne Argumente erzeugt, Klassen dagegen müssen explizit erzeugt werden. Weil Records einen argumentlosen Standardkonstruktor haben, muss jeder benutzerdefinierte Record-Konstruktor ein oder mehrere Parameter haben.
  • Record-Typen können keine Destruktoren haben.
  • Virtuelle Methoden (die mit den Schlüsselwörtern virtual, dynamic und message angegeben werden) dürfen in Record-Typen nicht verwendet werden.
  • Im Gegensatz zu Klassen können Record-Typen auf der Win32-Plattform keine Interfaces implementieren.

Dateitypen (Win32)

Dateitypen, die auf der Win32-Plattform zur Verfügung stehen, sind Folgen von Elementen desselben Typs. Für Standard-E/A-Routinen wird der vordefinierte Typ TextFile oder Text verwendet. Dieser Typ repräsentiert eine Datei, die in Zeilen angeordnete Zeichen enthält. Weitere Informationen zur Dateieingabe und -ausgabe finden Sie unter Standardroutinen und Eingabe-Ausgabe im Abschnitt "Dateiein- und -ausgabe".

Dateitypen werden mit der folgenden Syntax deklariert:

type fileTypeName = file of type

fileTypeName ist ein gültiger Bezeichner. type ist ein Typ fester Länge. Zeiger sind weder als implizite noch als explizite Typen erlaubt. Dynamische Arrays, lange Strings, Klassen, Objekte, Zeiger, Varianten, andere Dateien oder strukturierte Typen, die einen dieser Typen beinhalten, können deshalb nicht in Dateien enthalten sein.

Beispiel:

 type
    PhoneEntry = record
      FirstName, LastName: string[20];
      PhoneNumber: string[15];
      Listed: Boolean;
    end;
    PhoneList = file of PhoneEntry;

Hier wird ein Dateityp für die Aufzeichnung von Namen und Telefonnummern deklariert.

Die Konstruktion file of ... kann direkt in einer Variablendeklaration verwendet werden. Beispiel:

 var List1: file of PhoneEntry;

Das Wort file selbst gibt eine untypisierte Datei an:

 var DataFile: file;

Weitere Informationen hierzu finden Sie im Abschnitt "Untypisierte Dateien" in Standardroutinen und Eingabe-Ausgabe.

Dateitypen sind in Arrays und Records nicht erlaubt.

Siehe auch

Codebeispiele