home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / sibylft1.zip / DOC.DAT / DOC / OOP_REFG.INF (.txt) next >
OS/2 Help File  |  1996-04-14  |  72KB  |  2,647 lines

  1.  
  2. ΓòÉΓòÉΓòÉ 1. OOP Referenz f╨ær SpeedSoft Sibyl Version 2.0 ΓòÉΓòÉΓòÉ
  3.  
  4. This help is incomplete in this version ! It is only available in german for 
  5. now ! 
  6.  
  7.  Klassen
  8.  Sichtbarkeit
  9.  Instanzen
  10.  Zuweisungen
  11.  Felder
  12.  Methoden
  13.  Eigenschaften
  14.  Metaklassen
  15.  Vordefinierte Klassen
  16.  Exceptions
  17.  Vordefinierte Exceptions
  18.  
  19.  
  20. ΓòÉΓòÉΓòÉ 1.1. Klassen ΓòÉΓòÉΓòÉ
  21.  
  22.  ΓûäΓûäΓûäΓûäΓûäΓûäΓûä
  23.  Klassen
  24.  ΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇ
  25.  
  26. Was sind Klassen? 
  27.  
  28. Die Basis der objektorientierten Programmierung ist der Begriff der Klasse. Ein 
  29. Klasse ist ein strukturierter Datentyp, ╨öhnlich einem Record, jedoch weitaus 
  30. m╨öchtiger. 
  31.  
  32. Ein Repr╨ösentant einer Klasse wird eine Instanz oder ein Objekt der Klasse 
  33. genannt. Objekte sind dynamische Datentypen, die zur Laufzeit erzeugt und 
  34. zerst╨ñrt werden. Eine Klasse legt den Bauplan f╨ær jede ihrer Instanzen fest. 
  35.  
  36. Die Deklaration einer neuen Klasse kann drei Arten von Komponenten aufweisen: 
  37. Felder, Methoden und Eigenschaften. Zus╨ötzlich k╨ñnnen Klassen ╨æber den 
  38. Mechanismus der Vererbung die Komponenten einer bestehenden Klasse ╨æbernehmen. 
  39.  
  40. Jeder Komponente einer Klasse kann individuell ein Typ von Sichtbarkeit 
  41. zugeordnet werden. Dadurch wird festgelegt, wer die Komponente sehen und darauf 
  42. zugreifen kann. 
  43.  
  44. Deklaration von Klassen 
  45.  
  46. Klassen werden auf die folgende Weise deklariert: 
  47.  
  48. <Syntaxdiagramm Classes> 
  49.  
  50. Klassen k╨ñnnen nur im ╨öu╤üersten G╨æltigkeitsbereich eines Moduls deklariert 
  51. werden. Es ist nicht m╨ñglich, Klassen lokal in Prozeduren oder Funktionen zu 
  52. deklarieren. Es ist ebenfalls nicht m╨ñglich, Klassen im Rahmen einer 
  53. Variablen-Deklaration einzuf╨æhren. 
  54.  
  55. Es ist in Speed-Pascal ╨æblich, wenngleich nicht zwingend vorgeschrieben, da╤ü 
  56. die Bezeichner von Klassen mit einem 'T' beginnen, um sie als Typbezeichner 
  57. kenntlich zu machen. 
  58.  
  59. Komponenten einer Klasse 
  60.  
  61. Die Deklaration einer Klasse kann drei Arten von Komponenten aufweisen: Felder, 
  62. Methoden und Eigenschaften. 
  63.  
  64.      Felder 
  65.  
  66.       sind Variablen innerhalb einer Klasse und werden auf die gleiche Weise 
  67.       deklariert und benutzt wie die Felder eines Records. Jedes Objekt einer 
  68.       Klasse verf╨ægt ╨æber einen kompletten eigenen Satz aller Felder der 
  69.       Klasse. 
  70.  
  71.      Methoden 
  72.  
  73.       sind Prozeduren oder Funktionen, deren Funktionalit╨öt eng mit der Klasse 
  74.       verkn╨æpft ist. Methoden werden ╨æblicherweise in Verbindung mit einer 
  75.       Instanz aufgerufen. Alle Instanzen einer Klasse teilen sich den gleichen 
  76.       Satz Methoden, so da╤ü deren Code nur einmal im Programm vorhanden ist. 
  77.  
  78.      Eigenschaften 
  79.  
  80.       stellen sich dem Benutzer einer Klasse ╨öhnlich wie Felder dar, bieten 
  81.       jedoch weitaus mehr M╨ñglichkeiten. Lesende und schreibende Zugriffe auf 
  82.       eine Eigenschaft k╨ñnnen sowohl auf ein Feld als auch auf eine Methode 
  83.       umgelenkt werden. Im letzteren Fall wird bei der Ausf╨æhrung einer 
  84.       Zuweisung implizit die zugrundeliegende Methode aufgerufen. Au╤üerdem 
  85.       k╨ñnnen die Zugriffsm╨ñglichkeiten einer Eigenschaft auf nur-Lesen oder 
  86.       nur-Schreiben eingeschr╨önkt werden. 
  87.  
  88.  Vererbung 
  89.  
  90.  Bei der Deklaration einer neuen Klasse kann eine bereits bestehende Klasse als 
  91.  Vorfahr angegeben werden, wodurch die neue Klasse automatisch ╨æber s╨ömtliche 
  92.  Komponenten des Vorfahren verf╨ægt, sofern es deren Sichtbarkeit zul╨ö╤üt. 
  93.  
  94.  Zus╨ötzlich k╨ñnnen neue Komponenten deklariert oder vom Vorfahren geerbte 
  95.  Komponenten ╨æberschrieben werden. ╨¬berschreiben bedeutet, es wird f╨ær eine 
  96.  Komponente der neuen Klasse ein Bezeichner gew╨öhlt, der bereits im Vorfahren 
  97.  verwendet wird. Dadurch wird die ╨æberschriebene Komponente innerhalb der neuen 
  98.  Klasse verdeckt. Das ╨¬berschreiben hat aber keinen Einflu╤ü auf den Vorfahren 
  99.  selbst. 
  100.  
  101.  Es k╨ñnnen nur Methoden und Eigenschaften ╨æberschrieben werden, nicht jedoch 
  102.  Felder. Beim ╨¬berschreiben von Methoden ist es wichtig, das Laufzeitverhalten 
  103.  der verschiedenen Arten von Methoden zu kennen und die geeignete Art 
  104.  auszuw╨öhlen. 
  105.  
  106.  Achtung: Bei Borland Delphi ist es auch m╨ñglich, Felder des Vorfahren zu 
  107.  ╨æberschreiben. Bei Speed-Pascal besteht diese M╨ñglichkeit derzeit nicht. 
  108.  
  109.  Die Vererbung ist ein transitive Beziehung. Wenn zum Beispiel eine Klasse C 
  110.  von einer Klasse B abstammt, die wiederum von einer Klasse A abstammt, dann 
  111.  erbt B als Nachkomme von A deren Komponenten. C ist Nachkomme von B und damit 
  112.  auch Nachkomme von A. Zu den Komponenten, die C von B erbt, geh╨ñren also auch 
  113.  die von A. 
  114.  
  115.  Im folgenden Beispiel werden zwei Klassen TWindow und TEditorWindow 
  116.  deklariert. Da TEditorWindow ein Nachfahre von TWindow ist, besitzt die Klasse 
  117.  s╨ömtliche Komponenten von TWindow (FX, FY, FWidth, FHeight und die Methode 
  118.  Draw) sowie die beiden neuen Felder FCursorRow und FCursorColumn. 
  119.  
  120.   type
  121.     TWindow = class
  122.       FX, FY, FWidth, FHeight: Integer;
  123.       procedure Draw;
  124.     end;
  125.  
  126.     TEditorWindow = class(TWindow)
  127.       FCursorRow, FCursorColumn: Integer;
  128.     end;
  129.  
  130.  Durch mehrmalige Anwendung der Vererbung entsteht eine baumartige Hierarchie 
  131.  von Klassen. Es gibt keine Beschr╨önkung f╨ær die Anzahl der Nachkommen, die 
  132.  eine Klasse besitzen kann. Jede Klasse hat aber immer genau einen Vorfahren. 
  133.  
  134.  Wenn nicht explizit ein Vorfahr angegeben wird, dann nimmt der Compiler die in 
  135.  der Unit System vordefinierte Klasse TObject als Vorfahren an. 
  136.  
  137.  Damit sind die folgenden beiden Klassendeklarationen ╨öquivalent: 
  138.  
  139.   type
  140.     TMyObject = class           // impliziter Nachkomme von TObject
  141.       ...
  142.     end;
  143.  
  144.   type
  145.     TMyObject = class(TObject)  // expliziter Nachkomme von TObject
  146.       ...
  147.     end;
  148.  
  149.  Die Hierarchie der Klassen schl╨ögt sich auch in den Regeln f╨ær 
  150.  Zuweisungskompatibilit╨öt von Objekten nieder, die sich von denen f╨ær 
  151.  traditionelle Datentypen unterscheiden. 
  152.  
  153.  
  154. ΓòÉΓòÉΓòÉ 1.2. Sichtbarkeit ΓòÉΓòÉΓòÉ
  155.  
  156.  ΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûä
  157.  Sichtbarkeit
  158.  ΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇ
  159.  
  160. Was ist Sichtbarkeit? 
  161.  
  162. Die Sichtbarkeit einer Komponente bestimmt, wer diese Komponente sehen und 
  163. darauf zugreifen kann. 
  164.  
  165. Innerhalb des Moduls, in dem eine Klasse deklariert wird, sind immer alle ihre 
  166. Komponenten uneingeschr╨önkt sichtbar. Die Sichtbarkeit einer Komponente 
  167. au╤üerhalb dieses Moduls kann mit Hilfe der Schl╨æsselw╨ñrter public, protected 
  168. und private abgestuft eingeschr╨önkt werden. Zus╨ötzlich existiert mit published 
  169. eine Art von Sichtbarkeit, die Komponenten einer Klasse im Objekt-Inspektor der 
  170. Sibyl-Umgebung editierbar macht und spezielle Laufzeitinformationen erzeugt, 
  171. die von SPCC-Anwendungen ben╨ñtigt werden. 
  172.  
  173. Ein Sichtbarkeitsbezeichner wird in der Deklaration der Klasse vor einer 
  174. Komponente eingef╨ægt. Er gilt ab dieser Stelle entweder f╨ær alle folgenden 
  175. Komponenten der Klasse, oder bis eine andere Art der Sichtbarkeit festgelegt 
  176. wird. Die Sichtbarkeit einer Komponente vererbt sich auf die Nachfahren der 
  177. Klasse, kann aber in Nachfahren ge╨öndert werden, wenn die Komponente dort 
  178. sichtbar ist. 
  179.  
  180.      public - ╨⌐ffentliche Komponenten 
  181.  
  182.       Wenn keine andere Art der Sichtbarkeit vorgegeben wird, dann w╨öhlt der 
  183.       Compiler automatisch public. Komponenten, die als public gekennzeichnet 
  184.       werden, sind sowohl innerhalb als auch au╤üerhalb des Moduls, in dem die 
  185.       Klassendeklaration beheimatet ist, uneingeschr╨önkt sichtbar. 
  186.  
  187.       public ist die Art von Sichtbarkeit, die ╨æblicherweise f╨ær Komponenten 
  188.       gew╨öhlt wird, die dem Anwender einer Klasse zur Verf╨ægung stehen sollen. 
  189.  
  190.      protected - Gesch╨ætzte Komponenten 
  191.  
  192.       protected stellt eine etwas eingeschr╨önktere Art von Sichtbarkeit dar als 
  193.       public. Komponenten, die als protected gekennzeichnet werden, sind 
  194.       innerhalb des Moduls, in dem ihre Klasse deklariert wird, uneingeschr╨önkt 
  195.       sichtbar. Au╤üerhalb des Moduls sind sie nur innerhalb von Methoden von 
  196.       Nachfahren der Klasse sichtbar. 
  197.  
  198.       protected ist die Art von Sichtbarkeit, die ╨æblicherweise f╨ær Komponenten 
  199.       gew╨öhlt wird, die zwar dem Entwickler von Nachfahren der Klasse zur 
  200.       Verf╨ægung stehen, aber vor dem Anwender einer Klasse verborgen werden 
  201.       sollen. 
  202.  
  203.      private - Versteckte Komponenten 
  204.  
  205.       private ist die eingeschr╨önkteste Art von Sichtbarkeit. Komponenten die 
  206.       als private gekennzeichnet werden, sind innerhalb des Moduls, in dem ihre 
  207.       Klasse deklariert wird, uneingeschr╨önkt sichtbar. Au╤üerhalb des Moduls 
  208.       sind sie nicht sichtbar. 
  209.  
  210.       private ist die Art von Sichtbarkeit, die ╨æblicherweise f╨ær Komponenten 
  211.       gew╨öhlt wird, die im Rahmen der Kapselung g╨önzlich verborgen werden 
  212.       sollen. 
  213.  
  214.      published - Ver╨ñffentlichte Komponenten 
  215.  
  216.       published stellt eine besondere Art von Sichtbarkeit dar, die innerhalb 
  217.       der Sibyl-Umgebung zum Einsatz kommt. Komponenten, die als published 
  218.       gekennzeichnet werden, sind sowohl innerhalb als auch au╤üerhalb des 
  219.       Moduls, in dem ihre Klasse deklariert wird, uneingeschr╨önkt sichtbar. 
  220.       Damit verhalten sie sich exakt so wie Komponenten, die als public 
  221.       gekennzeichnet werden. 
  222.  
  223.       Zus╨ötzlich erzeugt der Compiler aber f╨ær Felder und Eigenschaften mit der 
  224.       Sichtbarkeit published spezielle Laufzeitinformationen, die f╨ær die 
  225.       Zusammenarbeit mit dem Objekt-Inspektor und f╨ær das Laufzeitverhalten von 
  226.       SPCC-Anwendungen von Bedeutung sind. 
  227.  
  228.       published ist die Art von Sichtbarkeit, die f╨ær Komponenten gew╨öhlt 
  229.       werden mu╤ü, die innerhalb des Objekt-Inspektors editierbar sein sollen. 
  230.       Zus╨ötzlich gelten folgende Einschr╨önkungen f╨ær Komponenten mit der 
  231.       Sichtbarkeit published: 
  232.  
  233.         -  Handelt es sich bei der Komponente um ein Feld, so mu╤ü dieses vom 
  234.            Typ einer Klasse sein. 
  235.  
  236.         -  Handelt es sich bei der Komponente um eine Eigenschaft, so mu╤ü diese 
  237.            einfach, also nicht-indiziert sein. Au╤üerdem ist ihr Typ auf eine 
  238.            der folgenden M╨ñglichkeiten beschr╨önkt: 
  239.  
  240.              -- Aufz╨öhlungstyp 
  241.  
  242.              -- Ganzzahliger Typ 
  243.  
  244.              -- Flie╤ükommazahl 
  245.  
  246.              -- String 
  247.  
  248.              -- Mengentyp mit nicht mehr als 16 Elementen 
  249.  
  250.              -- Objekttyp 
  251.  
  252.              -- Methodenzeiger 
  253.  
  254.  
  255. ΓòÉΓòÉΓòÉ 1.3. Instanzen ΓòÉΓòÉΓòÉ
  256.  
  257.  ΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûä
  258.  Instanzen
  259.  ΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇ
  260.  
  261. Was sind Instanzen? 
  262.  
  263. Ein Repr╨ösentant einer Klasse wird eine Instanz oder ein Objekt der Klasse 
  264. genannt. Objekte sind dynamische Datentypen, die zur Laufzeit erzeugt und 
  265. zerst╨ñrt werden. Eine Klasse legt den Bauplan f╨ær jede ihrer Instanzen fest. 
  266.  
  267. Das Erzeugen und Zerst╨ñren von Objekten geschieht mithilfe spezieller Methoden. 
  268. Zum Erzeugen eines Objekts wird ein Konstruktor aufgerufen, der den vom Objekt 
  269. ben╨ñtigten Speicherbereich auf dem Heap reserviert und initialisiert. Wird das 
  270. Objekt nicht mehr ben╨ñtigt, sollte es durch den Aufruf eines Destruktors 
  271. zerst╨ñrt werden, wodurch auch der reservierte Speicher wieder freigegeben wird. 
  272.  
  273. Das Objektmodell von Speed-Pascal basiert auf Referenzen. Eine Variable vom Typ 
  274. einer Klasse enth╨ölt kein Objekt, sondern einen Zeiger. Dieser Zeiger kann zur 
  275. Laufzeit ein Objekt referenzieren oder den Wert nil enthalten, um anzudeuten, 
  276. da╤ü er gerade kein g╨æltiges Objekt referenziert. Beim Erzeugen eines neuen 
  277. Objekts wird dem Zeiger die Adresse des Speicherbereiches zugewiesen, der f╨ær 
  278. das Objekt reserviert wurde. 
  279.  
  280. Es ist weder notwendig noch m╨ñglich, den Zeiger explizit zu dereferenzieren. 
  281. Der Compiler erledigt dies bei Bedarf. 
  282.  
  283.      Beim Zugriff auf die Elemente eines Objekts wird der Zeiger automatisch 
  284.       dereferenziert. Dadurch stellt sich ein Objekt trotz dynamischer 
  285.       Allokation wie eine statische Variable dar. 
  286.  
  287.      Beim Zugriff auf das gesamte Objekt wird der Zeiger nicht dereferenziert. 
  288.       Stattdessen wird mit dem Wert des Zeigers, also der Adresse der Instanz 
  289.       gearbeitet. Das wirkt sich insbesondere bei Zuweisungen aus. 
  290.  
  291.  Erzeugen von Instanzen 
  292.  
  293.  Instanzen werden erzeugt, indem eine spezielle Art von Methode aufgerufen 
  294.  wird, ein sogenannter Konstruktor. Der Konstruktur reserviert den f╨ær die 
  295.  Instanz n╨ñtigen Speicherbereich auf dem Heap und initialisiert das neue 
  296.  Objekt. Die Adresse der Instanz wird in eine Instanzvariable geschrieben, die 
  297.  zuvor deklariert sein mu╤ü. 
  298.  
  299.  Genauere Informationen zur Implementierung und zum Aufruf von Konstruktoren 
  300.  finden Sie im entsprechenden Abschnitt. 
  301.  
  302.  Zerst╨ñren von Instanzen 
  303.  
  304.  Objektinstanzen werden zerst╨ñrt, indem eine spezielle Art von Methode, ein 
  305.  sogenannter Destruktor aufgerufen wird. Der Destruktor f╨æhrt zuerst Code aus, 
  306.  der notwendig ist, um die Benutzung er Objektinstanz korrekt zu beenden. Das 
  307.  schlie╤üt insbesondere die Freigabe untergeordneter Objekte ein. Dieser Code 
  308.  wird vom Programmierer festgelegt. Dann gibt der Destruktor den vom Objekt auf 
  309.  dem Heap belegten Speicherplatz wieder frei. 
  310.  
  311.  Genauere Informationen zur Implementierung und zum Aufruf von Destruktoren 
  312.  finden Sie im entsprechenden Abschnitt. 
  313.  
  314.  
  315. ΓòÉΓòÉΓòÉ 1.4. Zuweisungen ΓòÉΓòÉΓòÉ
  316.  
  317.  ΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûä
  318.  Zuweisungen
  319.  ΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇ
  320.  
  321. Was geschieht bei Zuweisungen? 
  322.  
  323. Das Objektmodell von Speed-Pascal basiert auf Referenzen. Eine Variable vom Typ 
  324. einer Klasse bietet nicht Platz f╨ær eine Objektinstanz, sondern nur f╨ær einen 
  325. Zeiger, der eine Objektinstanz referenzieren kann. 
  326.  
  327. Bei einer Zuweisung wird demzufolge keine Kopie des Quellobjektes erstellt. 
  328. Stattdessen wird die Adresse des Objektes auf der rechten Seite der Zuweisung 
  329. in die Variable auf der linken Seite der Zuweisung geschrieben. Dadurch 
  330. referenzieren beide Variablen nach der Zuweisung das gleiche Objekt, was auch 
  331. das folgende Beispiel verdeutlicht. 
  332.  
  333. var
  334.   A, B: TObject;
  335.  
  336. begin
  337.   A.Create;   // Erzeugt eine Instanz von TObject. Die
  338.               // Variable A referenziert diese Instanz.
  339.  
  340.   B := A;     // Weist B den Wert von A zu. Beide Variablen
  341.               // referenzieren nun das gleiche Objekt.
  342.  
  343.   B.Destroy;  // Zerst╨ñrt die von B referenzierte Instanz.
  344.               // Damit ist auch der Wert von A ung╨æltig.
  345. end.
  346.  
  347. Zuweisungskompatibilit╨öt 
  348.  
  349. Durch den Vererbungsmechanismus ergeben sich verwandtschaftliche Beziehungen 
  350. zwischen Klassen. Diesen Beziehungen wird durch erweiterte M╨ñglichkeiten bei 
  351. Zuweisungen Rechnung getragen. 
  352.  
  353. Au╤üer mit sich selbst ist eine Klasse zuweisungskompatibel mit all ihren 
  354. Vorfahren. Das schlie╤üt sowohl den einen direkten als auch jeden weiteren 
  355. indirekten Vorfahren ein. Zur Laufzeit kann eine Variable vom Typ einer Klasse 
  356. A also eine Instanz genau dieser Klasse A oder eines beliebigen Nachfahren von 
  357. A referenzieren. 
  358.  
  359. Umgekehrt gilt diese Zuweisungskompatibilit╨öt nicht. Eine Klasse ist mit keinem 
  360. ihrer Nachfahren zuweisungskompatibel. Zwischen g╨önzlich unverwandten Klassen, 
  361. die v╨ñllig verschiedenen ╨₧sten der Objekthierarchie entstammen, besteht 
  362. ebenfalls keinerlei Zuweisungskompatibilit╨öt. 
  363.  
  364. Folgendes Beispiel demonstriert eine Reihe von legalen und illegalen 
  365. Zuweisungen. Illegale Zuweisungen werden vom Compiler erkannt und nicht 
  366. akzeptiert. 
  367.  
  368. type
  369.   TVehicle   = class(TObject);
  370.   TShip      = class(TVehicle);
  371.   TSubmarine = class(TShip);
  372.  
  373.   TAirplane  = class(TVehicle);
  374.  
  375. var
  376.   Vehicle:   TVehicle;
  377.   Ship:      TShip;
  378.   Submarine: TSubmarine;
  379.   Airplane:  TAirplane;
  380.  
  381. begin
  382.   // Die folgenden Zuweisungen sind g╨æltig.
  383.  
  384.   Vehicle := Ship;
  385.   Vehicle := Submarine;
  386.   Vehicle := Airplane;
  387.  
  388.   Ship    := Submarine;
  389.  
  390.   // Die folgenden Zuweisungen sind ung╨æltig
  391.   // und werden vom Compiler nicht akzeptiert.
  392.  
  393.   Ship      := Vehicle;  // TShip ist Nachkomme von TVehicle.
  394.   Submarine := Vehicle;  // TSubmarine ist Nachkomme von TVehicle.
  395.   Airplane  := Vehicle;  // TAirplane ist Nachkomme von TVehicle.
  396.  
  397.   Submarine := Ship;     // TSubmarine ist Nachkomme von TShip.
  398.  
  399.   Ship      := Airplane; // TShip und TAirplane sind nicht verwandt.
  400.   Airplane  := Ship;     // TAirplane und TShip sind nicht verwandt.
  401. end.
  402.  
  403. Typwandlungen 
  404.  
  405. Bei Objekten k╨ñnnen - wie bei anderen Datentypen auch - Typwandlungen 
  406. durchgef╨æhrt werden. Durch eine Typwandlung wird die Typpr╨æfung von 
  407. Speed-Pascal bewu╤üt unterlaufen, wodurch sich potentielle Gefahren ergeben. Um 
  408. diese Gefahren zu minimieren, bietet Speed-Pascal mit is und as zwei 
  409. Operatoren, die unter anderem sichere Typwandlungen erm╨ñglichen. 
  410.  
  411.      Der Operator is 
  412.  
  413.       Der Operator is dient dazu, zur Laufzeit eine Typpr╨æfung f╨ær ein Objekt 
  414.       durchzuf╨æhren. Die Syntax ist: 
  415.  
  416.               MyObject is MyClass
  417.  
  418.       Das Ergebnis dieses Ausdrucks ist vom Typ Boolean. Zur Laufzeit wird der 
  419.       tats╨öchliche Typ des Objekts MyObject mit der Klasse MyClass verglichen. 
  420.       Ist der Typ von MyObject identisch mit MyClass oder einem beliebigen 
  421.       direkten oder indirekten Nachfahren von MyClass, dann ist das Ergebnis 
  422.       des Ausdrucks True. In allen anderen F╨öllen, insbesondere wenn MyObject 
  423.       nil ist, liefert die Anwendung des Operators den Wert False. 
  424.  
  425.             type
  426.               TVehicle  = class(TObject);
  427.               TShip     = class(TVehicle);
  428.               TAirplane = class(TVehicle);
  429.  
  430.             var
  431.               MyVehicle: TVehicle;
  432.  
  433.             begin
  434.               ...
  435.               if MyVehicle is TShip then WriteLn('Es ist ein Schiff.')
  436.               else if MyVehicle is TAirplane then WriteLn('Es ist ein Flugzeug.');
  437.               ...
  438.             end.
  439.  
  440.       Beachten Sie, da╤ü MyClass nicht unmittelbar den Namen einer Klasse 
  441.       angeben mu╤ü, sondern auch eine Variable vom Typ einer Metaklasse sein 
  442.       kann. Die tats╨öchliche Klasse wird dann zur Laufzeit dieser Variablen 
  443.       entnommen. N╨öheres dazu entnehmen Sie bitte dem Abschnitt ╨æber 
  444.       Metaklassen. 
  445.  
  446.      Der Operator as 
  447.  
  448.       Der Operator as dient dazu, zur Laufzeit sichere Typwandlungen 
  449.       durchzuf╨æhren. Die Syntax ist: 
  450.  
  451.               MyObject as MyClass
  452.  
  453.       Das Ergebnis des Ausdrucks ist vom Typ MyClass. Zur Laufzeit wird anhand 
  454.       des tats╨öchlichen Typs von MyObject gepr╨æft, ob die Typwandlung sicher 
  455.       ist. Als sicher gilt die Typwandlung genau dann, wenn MyClass identisch 
  456.       mit dem tats╨öchlichen Typ von MyObject oder ein direkter oder indirekter 
  457.       Vorfahre davon ist. Ist diese Bedingung nicht erf╨ællt, dann wird eine 
  458.       Exception ausgel╨ñst. 
  459.  
  460.       Sie k╨ñnnen den Operator mit with..do kombinieren, um eine Reihe von 
  461.       Operationen auf einem Objekt nur dann durchzuf╨æhren, wenn das Objekt 
  462.       zuweisungskompatibel zu einer bestimmten Klasse ist. 
  463.  
  464.             var
  465.               MyStream: TStream;
  466.  
  467.             begin
  468.               ...
  469.               with MyStream as THandleStream do  // Wenn MyStream zuweisungskompatibel
  470.               begin                              // zu THandleStream ist, dann wird der
  471.                 WriteLn('Handle: ', Handle);     // Block ausgef╨æhrt. Sonst wird eine
  472.               end;                               // Exception ausgel╨ñst.
  473.               ...
  474.             end;
  475.  
  476.       Beachten Sie, da╤ü MyClass nicht unmittelbar den Namen einer Klasse 
  477.       angeben mu╤ü, sondern auch eine Variable vom Typ einer Metaklasse sein 
  478.       kann. Die tats╨öchliche Klasse wird dann zur Laufzeit dieser Variablen 
  479.       entnommen. N╨öheres dazu entnehmen Sie bitte dem Abschnitt ╨æber 
  480.       Metaklassen. 
  481.  
  482.       Beachten Sie au╤üerdem, da╤ü die Typwandlung auch dann als sicher gilt, 
  483.       wenn MyObject den Wert nil enth╨ölt. Wenn Sie nicht sicher sind, ob 
  484.       MyObject wirklich ein g╨æltiges Objekt referenziert, dann sollten Sie dies 
  485.       zuerst pr╨æfen. Anderenfalls riskieren Sie den Abbruch des Programms mit 
  486.       einer Schutzverletzung. 
  487.  
  488.  
  489. ΓòÉΓòÉΓòÉ 1.5. Felder ΓòÉΓòÉΓòÉ
  490.  
  491.  ΓûäΓûäΓûäΓûäΓûäΓûä
  492.  Felder
  493.  ΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇ
  494.  
  495. Was sind Felder? 
  496.  
  497. Felder sind Variablen innerhalb einer Klasse. 
  498.  
  499. Sie entsprechen in Deklaration und Anwendung weitgehend den Feldern von 
  500. Records. Jedes Objekt verf╨ægt ╨æber einen eigenen Satz aller Felder seiner 
  501. Klasse, insbesondere auch der Felder, die die Klasse von ihren Vorfahren geerbt 
  502. hat. 
  503.  
  504. Das ╨₧ndern eines Feldes von Objekt A hat keinen Einflu╤ü auf das gleichnamige 
  505. Feld eines Objekts B der gleichen Klasse, solange die Variablen A und B nicht 
  506. die gleiche Instanz referenzieren. Hingegen teilen sich alle Objekte einer 
  507. Klasse den gleichen Satz Methoden, wodurch deren Code nur einmal vorhanden ist. 
  508.  
  509. Deklaration von Feldern 
  510.  
  511. Felder werden auf die folgende Weise deklariert: 
  512.  
  513. <Syntaxdiagramm: Fields> 
  514.  
  515. Es ist in Speed-Pascal ╨æblich, wenngleich nicht zwingend vorgeschrieben, da╤ü 
  516. Feldbezeichner mit einem F beginnen. 
  517.  
  518. Folgendes Beispiel zeigt die Deklaration von Feldern. 
  519.  
  520. type
  521.   TCity = class
  522.     FName: string;
  523.     FLongitude, FLatitude: Integer;
  524.     FPopulation: LongWord;
  525.   end;
  526.  
  527. Alle Instanzen der Klasse TCity verf╨ægen ╨æber ihre eigenen Felder zur Aufnahme 
  528. von Name, geographischer Position und Bev╨ñlkerungszahl einer Stadt. 
  529.  
  530. Benutzen von Feldern 
  531.  
  532. Die Zugriffe auf die Felder eines Objekts entsprechen den Zugriffen auf Felder 
  533. von Records. Einzelne Felder k╨ñnnen ╨æber den Punkt und den Bezeichner des 
  534. Feldes selektiert werden. Au╤üerdem kann eine Operation auf einem Objekt durch 
  535. with..do angef╨æhrt werden, wodurch alle Felder des Objekts direkt ansprechbar 
  536. werden. 
  537.  
  538. type
  539.   TCompiler = class
  540.     FName: string;
  541.     FVersionHi, FVersionLo: Integer;
  542.   end;
  543.  
  544. var
  545.   MyCompiler: TCompiler;
  546.  
  547. begin
  548.   ...
  549.  
  550.   // Qualifizierter Zugriff auf die Felder des Objekts.
  551.  
  552.   MyCompiler.FName := 'Speed-Pascal/2';
  553.   MyCompiler.FVersionHi := 2;
  554.   MyCompiler.FVersionLo := 0;
  555.  
  556.   // Zugriff auf die Felder mit Hilfe von WITH..DO. Die
  557.   // folgende Sequenz hat die gleiche Wirkung wie die
  558.   // vorangehende.
  559.  
  560.   with MyCompiler do
  561.   begin
  562.     FName := 'Speed-Pascal/2';
  563.     FVersionHi := 2;
  564.     FVersionLo := 0;
  565.   end;
  566.  
  567.   // Lesender Zugriff, WITH..DO ohne BEGIN..END.
  568.  
  569.   with MyCompiler do
  570.     WriteLn(FName, ' Version ', FVersionHi, '.', FVersionLo);
  571.  
  572.   ...
  573. end.
  574.  
  575.  
  576. ΓòÉΓòÉΓòÉ 1.6. Methoden ΓòÉΓòÉΓòÉ
  577.  
  578.  ΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûä
  579.  Methoden
  580.  ΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇ
  581.  
  582. Was sind Methoden? 
  583.  
  584. Methoden sind Prozeduren oder Funktionen, deren Funktionalit╨öt fest mit einer 
  585. Klasse verkn╨æpft ist. 
  586.  
  587. Methoden werden ╨æblicherweise in Verbindung mit einer Instanz der Klasse 
  588. aufgerufen. Bei Klassenmethoden ist auch ein Aufruf in Verbindung mit einer 
  589. Klasse m╨ñglich. Felder, Methoden und Eigenschaften einer Klasse sind innerhalb 
  590. der Implementierung ihrer Methoden verf╨ægbar. 
  591.  
  592. Methoden werden an Nachfahren vererbt. Alle Instanzen einer Klasse teilen sich 
  593. den gleichen Satz Methoden, so da╤ü deren Code nur einmal im Programm vorhanden 
  594. ist. 
  595.  
  596. Es gibt eine Reihe von Schl╨æsselw╨ñrtern, die das Laufzeitverhalten einer 
  597. Methode beeinflussen. W╨öhrend bei statischen Methoden die Aufrufadresse bereits 
  598. zur Zeit der Compilierung feststeht, wird sie bei virtuellen und dynamischen 
  599. Methoden erst zur Laufzeit ermittelt. Zus╨ötzlich existieren 
  600. botschaftsverarbeitende Methoden, die das Zusammenspiel verschiedener 
  601. Bildschirmelemente mit dem Betriebssystem ╨æber den Austausch von Nachrichten 
  602. koordinieren. 
  603.  
  604. Zwei spezielle Arten von Methoden, Konstruktoren und Destruktoren, dienen zum 
  605. Erzeugen und Zerst╨ñren von Objektinstanzen. 
  606.  
  607. Deklarieren von Methoden 
  608.  
  609. Methoden werden auf die folgende Weise deklariert: 
  610.  
  611. <Syntaxdiagramm: Methods> 
  612.  
  613. Folgendes Beispiel deklariert eine Klasse TWindow zur Darstellung eines 
  614. Fensters auf dem Bildschirm. Die Klasse enth╨ölt zwei Methoden zum Lesen und 
  615. Schreiben des Fenstertitels. 
  616.  
  617. type
  618.   TWindow = class
  619.     ...
  620.     function GetTitle: string;
  621.                 procedure SetTitle(const S: string);
  622.     ...
  623.   end;
  624.  
  625. Implementieren von Methoden 
  626.  
  627. Die Methoden einer Klasse werden nach der Deklaration der Klasse implementiert, 
  628. ╨öhnlich der Implementierung einer als forward deklarierten Prozedur oder 
  629. Funktion. 
  630.  
  631. Falls die Klasse in einer Unit deklariert wird, findet die Implementierung der 
  632. Methoden im implementation-Teil der Unit statt. 
  633.  
  634. Jeder einzelnen Methode geht bei der Implementierung der Name der Klasse 
  635. gefolgt von einem Punkt voran. 
  636.  
  637. Die Liste formaler Parameter der Methode kann, mu╤ü aber nicht bei der 
  638. Implementierung wiederholt werden. Wenn sie wiederholt wird, dann mu╤ü sie exakt 
  639. mit der Parameterliste der Deklaration ╨æbereinstimmen. 
  640.  
  641. type
  642.   TWindow = class
  643.     X, Y, Width, Height: Integer;
  644.     Title: string;
  645.     ...
  646.     procedure Draw;
  647.     procedure SetPosition(X, Y: Integer);
  648.     procedure SetTitle(const S: string);
  649.   end;
  650.  
  651. // Draw besitzt keine Parameter.
  652.  
  653. procedure TWindow.Draw;
  654. begin
  655.   ...
  656. end;
  657.  
  658. // Bei SetPosition wird die gesamte Parameterliste wiederholt.
  659.  
  660. procedure TWindow.SetPosition(X, Y: Integer);
  661. begin
  662.   ...
  663. end;
  664.  
  665. // Bei SetTitle wird die gesamte Parameterliste weggelassen.
  666.  
  667. procedure TWindow.SetTitle;
  668. begin
  669.   ...
  670. end;
  671.  
  672. Der G╨æltigkeitsbereich aller Komponenten einer Klasse erstreckt sich unter 
  673. anderem auf die Implementierung aller Methoden der Klasse. Dadurch sind alle 
  674. Felder, Methoden und Eigenschaften der Klasse innerhalb der Methode direkt 
  675. zugreifbar. 
  676.  
  677. procedure TWindow.SetTitle(const S: string);
  678. begin
  679.   FTitle := S;
  680.   Draw;
  681. end;
  682.  
  683. Zus╨ötzlich existiert in jeder Methode ein impliziter Parameter Self, der vom 
  684. Typ der Klasse ist, zu der die Methode geh╨ñrt. Self referenziert zur Laufzeit 
  685. stets das Objekt, auf dem die Methode aufgerufen wurde. Wenn durch eine 
  686. with..do-Anweisung oder durch formale Parameter der Methode Komponenten der 
  687. Klasse aus dem aktuellen G╨æltigkeitsbereich verdr╨öngt werden, dann kann ╨æber 
  688. Self weiterhin auf diese Komponenten zugegriffen werden. 
  689.  
  690. procedure TWindow.SetPosition(X, Y: Integer);
  691. begin
  692.   // Der Konflikt zwischen den Feldern X, Y und den
  693.   // gleichnamigen formalen Parametern wird durch
  694.   // Self gel╨ñst.
  695.  
  696.   Self.X := X;
  697.   Self.Y := Y;
  698.  
  699.   Draw;
  700. end;
  701.  
  702. Falls innerhalb der Implementierung einer Methode einer Klasse auf eine 
  703. gleichnamige Methode des Vorfahren zugegriffen werden soll, die in der neuen 
  704. Klasse ╨æberschrieben oder verdeckt wurde, dann ist dies mit dem Schl╨æsselwort 
  705. inherited m╨ñglich. 
  706.  
  707. type
  708.   TEditorWindow = class(TWindow)
  709.     procedure Draw;
  710.   end;
  711.  
  712. procedure TWindow.Draw;
  713. begin
  714.   DrawFrameAndTitle;  // Soll den den Rahmen und die Titelzeile zeichnen.
  715. end;
  716.  
  717. procedure TEditorWindow.Draw;
  718. begin
  719.   inherited Draw;     // Ruft zuerst TWindow.Draw auf.
  720.   DrawContents;       // Soll den Inhalt des Editor-Fensters zeichnen.
  721. end;
  722.  
  723. Aufruf von Methoden 
  724.  
  725. Der Aufruf einer Methode geschieht durch Angabe der Instanz, auf der die 
  726. Methode operieren soll, gefolgt von einem Punkt, dem Namen der Methode und der 
  727. Liste aktueller Parameter. Innerhalb einer with..do-Anweisung, die eine 
  728. Objektinstanz in den aktuellen G╨æltigkeitsbereich r╨æckt, kann die Angabe der 
  729. Instanz auch entfallen. 
  730.  
  731. type
  732.   TWindow = class
  733.     procedure SetPosition(X, Y: Integer);
  734.   end;
  735.  
  736. var
  737.   MyWindow: TWindow;
  738.  
  739. begin
  740.   ...
  741.   MyWindow.SetPosition(100, 200);  // Qualifizierter Aufruf.
  742.   ...
  743.   with MyWindow do
  744.   begin
  745.     SetPosition(100, 200);         // Aufruf innerhalb von WITH..DO
  746.   end;                             // ben╨ñtigt keine Angabe der Instanz.
  747.   ...
  748. end.
  749.  
  750. Bei Klassenmethoden besteht zus╨ötzlich die M╨ñglichkeit, die Methode mit dem 
  751. Bezeichner einer Klasse anstelle der Objektinstanz aufzurufen. 
  752.  
  753. Welche Methode zur Laufzeit tats╨öchlich aufgerufen, h╨öngt wesentlich davon ab, 
  754. welches Laufzeitverhalten f╨ær die Methode gew╨öhlt wurde. W╨öhrend bei statischen 
  755. Methoden die Bindung bereits zur Zeit der Compilierung durchgef╨æhrt wird, 
  756. ermittelt bei virtuellen oder dynamischen Methoden das Laufzeitsystem anhand 
  757. des tats╨öchlichen Typs der Instanz, welche Methode aufgerufen wird. 
  758.  
  759. Spezielle Arten von Methoden 
  760.  
  761.      Statische Methoden 
  762.  
  763.       Sofern bei der Deklaration einer Methode keine andere Art der 
  764.       Methodenzuteilung gew╨öhlt wird, ist die Methode statisch. 
  765.  
  766.       Die Adresse der aufzurufenden Methode steht dann bereits zur Zeit der 
  767.       Compilierung fest und wird vom Linker fest ins Programm eingetragen. 
  768.  
  769.      Virtuelle Methoden 
  770.  
  771.       Das Laufzeitverhalten einer Methode wird als virtuell festgelegt, wenn an 
  772.       die Deklaration der Methode das Schl╨æsselwort virtual angeh╨öngt wird. 
  773.  
  774.       Bei virtuellen Methoden steht die Adresse des Aufrufes nicht bereits zur 
  775.       Zeit der Compilierung fest. Stattdessen wird diese Entscheidung auf die 
  776.       Laufzeit des Programms verschoben. Das Laufzeitsystem ermittelt anhand 
  777.       des tats╨öchlichen Typs der Instanz, welche Methode aufgerufen wird. 
  778.  
  779.       Wenn eine Methode einmal als virtuell festgelegt wird, dann gilt dies 
  780.       automatisch auch f╨ær alle Nachfahren der Klasse, zu der die Methode 
  781.       geh╨ñrt. Das bedeutet insbesondere, da╤ü die einmal festgelegte Liste 
  782.       formaler Parameter beim ╨¬berschreiben der Methode beibehalten werden mu╤ü. 
  783.       Zum ╨¬berschreiben einer virtuellen Methode wird das Schl╨æsselwort 
  784.       override anstelle von virtual eingesetzt. 
  785.  
  786.       Folgendes Beispiel zeigt einen typischen Einsatzfall f╨ær eine virtuelle 
  787.       Methode. Verschiedene graphische Bildschirmelemente besitzen eine Methode 
  788.       Draw, mit der sie neu gezeichnet werden. Dadurch, da╤ü diese Methode 
  789.       virtuell ist, wird zur Laufzeit stets die zur Instanz passende Version 
  790.       von Draw aufgerufen. Bei einer statischen Methode hingegen w╨ærde stets 
  791.       die Version von Draw aufgerufen, die zum deklarierten Typ der Variablen 
  792.       geh╨ñrt, im Beispiel also TWindow.Draw. 
  793.  
  794.             type
  795.               TWindow = class(TObject)
  796.                  procedure Draw; virtual;    // Kennzeichnet die Methode als virtuell.
  797.               end;
  798.  
  799.               TEditorWindow = class(TWindow)
  800.                 procedure Draw; override;    // ╨¬berschreibt die virtuelle Methode.
  801.               end;
  802.  
  803.               ...
  804.  
  805.             var
  806.               MyWindow: TWindow;
  807.  
  808.             begin
  809.               MyWindow := TWindow.Create;        // Erzeugt eine Instanz von TWindow.
  810.  
  811.               MyWindow.Draw;                     // Ruft TWindow.Draw auf.
  812.  
  813.               MyWindow.Destroy;                  // Zerst╨ñrt die Instanz.
  814.  
  815.               MyWindow := TEditorWindow.Create;  // Erzeugt eine neue Instanz von
  816.                                                  // TEditorWindow
  817.  
  818.               MyWindow.Draw;                     // Ruft TEditorWindow.Draw auf. W╨öre
  819.                                                  // Draw nicht virtuell, w╨ærde hier
  820.                                                  // auch TWindow.Draw aufgerufen, was
  821.                                                  // in diesem Fall sicher nicht sehr
  822.                                                  // sinnvoll ist.
  823.  
  824.               MyWindow.Destroy;                  // Zerst╨ñrt die Instanz.
  825.             end.
  826.  
  827.       Es ist auch m╨ñglich, eine virtuelle Methode in einem Nachfahren neu zu 
  828.       deklarieren. Dadurch wird die geerbte virtuelle Methode in der neuen 
  829.       Klasse verdeckt, analog zu einer statischen Methode, die durch die 
  830.       Neudeklaration einer statischen Methode gleichen Namens verdeckt wird. 
  831.       Die neu deklarierte Methode mu╤ü dabei wieder eine als virtual 
  832.       gekennzeichnete virtuelle Methode sein, jedoch kann sich ihre Liste 
  833.       formaler Parameter von der der verdeckten Methode unterscheiden. 
  834.  
  835.       Das Verhalten von auf diese Weise neu deklarierten virtuellen Methoden 
  836.       ist aber unter Umst╨önden schwerer zu durchschauen als das von 
  837.       ╨æberschriebenen virtuellen Methoden. Sie sollten deshalb eine einmal als 
  838.       virtuell gekennzeichnete Methode stets mit override ╨æberschreiben. 
  839.  
  840.       Achtung: Im Gegensatz zu Borland Delphi ist es bei Speed-Pascal derzeit 
  841.       nicht m╨ñglich, da╤ü eine virtuelle Methode durch die Neudeklaration einer 
  842.       statischen Methode in einem Nachfahren verdeckt wird. Der Compiler 
  843.       verbietet dies, um Fehler seitens des Programmierers abzufangen. 
  844.       Normalerweise handelt es sich dabei eher um ein vergessenes override als 
  845.       um eine gewollte Neudeklaration. Diese Art von Fehler ist aber meist 
  846.       schwer zu entdecken, weil das Programm korrekt compiliert wird, und sich 
  847.       das falsche Verhalten der Methode nur in einzelnen F╨öllen und oft nur auf 
  848.       sehr subtile Weise bemerkbar macht. 
  849.  
  850.       Virtuelle Methoden werden vom Compiler mit Hilfe einer Tabelle virtueller 
  851.       Methoden realisiert. Jede Klasse besitzt eine solche Tabelle mit den 
  852.       Einsprungadressen aller ihrer virtuellen Methoden. Zur Laufzeit wird die 
  853.       Adresse der aufzurufenden Methode aus dieser Tabelle ermittelt. Der 
  854.       Aufrufmechanismus ist sehr schnell, ben╨ñtigt aber dennoch minimal mehr 
  855.       Zeit als der Aufruf einer statischen Methode. 
  856.  
  857.       Virtuelle Methoden sind ein m╨öchtiges Hilfsmittel, um Polymorphie zu 
  858.       erreichen. 
  859.  
  860.      Dynamische Methoden 
  861.  
  862.       Das Laufzeitverhalten einer Methode wird als dynamisch festgelegt, wenn 
  863.       an die Deklaration der Methode das Schl╨æsselwort dynamic angeh╨öngt wird. 
  864.  
  865.       Dynamische Methoden verhalten sich exakt so wie virtuelle Methoden, 
  866.       insbesondere was das ╨¬berschreiben und die Neudeklaration betrifft. 
  867.  
  868.       Achtung: Das Schl╨æsselwort existiert nur aus Gr╨ænden der Kompatibilit╨öt 
  869.       zu Borland Delphi. Programme, die auf dynamische Methoden zur╨æckgreifen, 
  870.       werden unter Speed-Pascal problemlos funktionieren. Jedoch werden sie 
  871.       vermutlich geringf╨ægige Unterschiede in Ausf╨æhrungsgeschwindigkeit und 
  872.       Speicherbedarf aufweisen. 
  873.  
  874.      Abstrakte Methoden 
  875.  
  876.       Eine virtuelle oder dynamische Methode wird zu einer abstrakten Methode, 
  877.       wenn an die Deklaration der Methode das Schl╨æsselwort abstract angeh╨öngt 
  878.       wird. 
  879.  
  880.       Nur virtuelle und dynamische Methoden k╨ñnnen abstrakt sein, nicht jedoch 
  881.       statische. Das Schl╨æsselwort abstract mu╤ü dabei dem Schl╨æsselwort virtual 
  882.       oder dynamic folgen. 
  883.  
  884.       Abstrakte Methoden werden nicht implementiert, k╨ñnnen jedoch von anderen 
  885.       Methoden oder von Code, der nicht Teil einer Methode ist, benutzt werden. 
  886.       Ihr Sinn liegt darin, ein funktionsloses Interface bereitzustellen, das 
  887.       von Nachfahren einer Klasse aufrechterhalten werden mu╤ü. Spezialisierte 
  888.       Nachfahren m╨æssen abstrakte Methoden mit override ╨æberschreiben, wenn die 
  889.       Methode tats╨öchlich genutzt werden soll. Der Aufruf einer abstrakten 
  890.       Methode auf einer Instanz, deren Klasse die Methode nicht ╨æberschreibt, 
  891.       f╨æhrt zu einem Laufzeitfehler. 
  892.  
  893.       Innerhalb der Implementierung einer Methode, die eine abstrakte Methode 
  894.       ╨æberschreibt, kann nicht mit inherited auf die Methode des Vorfahren 
  895.       zugegriffen werden. 
  896.  
  897.       Folgendes Beispiel deklariert eine Basisklasse TContainer f╨ær 
  898.       Container-Objekte. Sie verf╨ægt ╨æber zwei abstrakte Methoden zum Vergleich 
  899.       und zum Vertauschen zweier Elemente anhand ihrer Indizes. Au╤üerdem 
  900.       beinhaltet die Klasse eine Sortiermethode. Innerhalb der Sortiermethode 
  901.       k╨ñnnen die beiden abstrakten Methoden 
  902.  
  903.             type
  904.               TContainer = class
  905.                 FSize: Integer;
  906.  
  907.                 function BiggerThan(Item1, Item2: Integer): Boolean; virtual; abstract;
  908.                 procedure Swap(Item1, Item2: Integer); virtual; abstract;
  909.                 procedure BubbleSort;
  910.               end;
  911.  
  912.             procedure TContainer.BubbleSort;
  913.             var
  914.               N, I: Integer;
  915.             begin
  916.               for N := FSize downto 2 do
  917.                 for I := 1 to N - 1 do
  918.                   if BiggerThan(I, I + 1) then Swap(I, I + 1);
  919.             end;
  920.  
  921.      Botschaftsverarbeitende Methoden 
  922.  
  923.       Eine Methode wird zu einer botschaftsverarbeitenden Methode, indem an 
  924.       ihre Deklaration das Schl╨æsselwort message gefolgt von einer 
  925.       ganzzahligen, positiven Konstanten angeh╨öngt wird. 
  926.  
  927.       Zus╨ötzlich mu╤ü die Methode eine Prozedurmethode sein, die ╨æber genau 
  928.       einen var-Parameter beliebigen Typs verf╨ægt. Auch ein untypisierter 
  929.       var-Parameter ist erlaubt. 
  930.  
  931.             type
  932.               TMyButton = class(TButton)
  933.                 ...
  934.                 procedure WMButton1Down(var Message); message WM_BUTTON1DOWN;
  935.                 ...
  936.               end;
  937.  
  938.       Botschaftsverarbeitende Methoden dienen ╨æblicherweise zum Austausch von 
  939.       Nachrichten mit dem Betriebssystem, insbesondere bei der Programmierung 
  940.       von graphischen Oberfl╨öchen wie dem OS/2 Presentation Manager oder 
  941.       Windows. So wird zum Beispiel bei einem Tastendruck oder einem Mausklick 
  942.       vom Betriebssystem eine Botschaft an das zugeh╨ñrige Bildschirmobjekt 
  943.       gesandt, das diese Botschaft dann verarbeiten mu╤ü. Es wird genau die 
  944.       botschaftsverarbeitende Methode aufgerufen, deren hinter message 
  945.       angegebene Nummer mit der Identifikation der Nachricht ╨æbereinstimmt. 
  946.  
  947.       Es ist m╨ñglich, weitere Informationen an eine solche Methode zu 
  948.       ╨æbergeben. Dazu dient der var-Parameter, der die ╨¬bergabe fast beliebiger 
  949.       Typen erlaubt. Wichtig f╨ær das Funktionieren des Botschaftsmechanismus 
  950.       ist nur, da╤ü die ersten vier Byte des Parameters die Nummer der Botschaft 
  951.       enthalten. Die darauf folgenden Daten k╨ñnnen vom Programmierer frei 
  952.       gew╨öhlt werden. Damit sehen alle zul╨össigen Parameter-Typen etwa wie 
  953.       folgt aus: 
  954.  
  955.             type
  956.               TMessageRec = record
  957.                 MessageID: LongWord; // Die Identifikation der Nachricht.
  958.                 ...                  // Ab hier beliebige weitere Informationen.
  959.               end;
  960.  
  961.       Der OS/2 Presentation Manager und Windows erlauben beim Austausch die 
  962.       ╨¬bergabe von zwei zus╨ötzlichen 32 Bit breiten Parametern, die je nach Art 
  963.       der Nachricht in mehrere logische 16 oder 8 Bit breite Parameter 
  964.       unterteilt sein k╨ñnnen. Daher ist f╨ær Anwendungen, die auf die 
  965.       SPCC-Bibliothek zur╨æckgreifen, in der Unit Classes bereits ein 
  966.       Botschaftstyp TMessage deklariert, der diesen Fall abdeckt. 
  967.  
  968.       Es ist m╨ñglich und ausgesprochen sinnvoll, botschaftsverarbeitende 
  969.       Methoden bei Nachfahren einer Klasse zu ╨æberschreiben, um ein vom 
  970.       Vorfahren abweichendes Verhalten bei bestimmten Nachrichten zu 
  971.       realisieren. Anders als bei virtuellen Methoden ist hier beim 
  972.       ╨¬berschreiben das Schl╨æsselwort override nicht notwendig. 
  973.       Botschaftsverarbeitende Methoden sind immer dynamisch gebunden; das 
  974.       hei╤üt, die Adresse des Aufrufes wird immer zur Laufzeit anhand des 
  975.       tats╨öchlichen Typs der Instanz ermittelt. Dazu legt der Compiler f╨ær jede 
  976.       Klasse eine Tabelle von botschaftsverarbeitenden Methoden mit deren 
  977.       Nummern und Einsprungsadressen an. 
  978.  
  979.       Die Informationen dieser Tabelle werden von einer Methode Dispatch 
  980.       ausgewertet, die von TObject bereitgestellt wird. Da alle Objekte 
  981.       Nachfahren von TObject sind, steht diese Methode in jedem Objekt zur 
  982.       Verf╨ægung. 
  983.  
  984.             procedure Dispatch(var Message);
  985.  
  986.       Botschaftsverarbeitende Methoden werden ╨æblicherweise nicht direkt 
  987.       aufgerufen, sondern ╨æber einen Aufruf von Dispatch mit einem geeigneten 
  988.       Parameter, der die Nummer der Nachricht und m╨ñglicherweise weitere 
  989.       Informationen enth╨ölt. 
  990.  
  991.       Dispatch erledigt das Auffinden der zur Botschaft passenden Methode und 
  992.       ruft diese dann auf. Dazu sucht Dispatch sucht zuerst in der Tabelle der 
  993.       tats╨öchlichen Klasse der Instanz nach einer Methode mit der in der 
  994.       Botschaft enthaltenen Nummer. Ist dort keine solche Methode enthalten, 
  995.       wird die Tabelle des Vorfahren der Klasse durchsucht, dann die von dessen 
  996.       Vorfahren, und so weiter. 
  997.  
  998.       Es ist wichtig zu wissen, da╤ü f╨ær den Aufruf einer 
  999.       botschaftsverarbeitenden Methode ╨æber Dispatch nur deren Nummer 
  1000.       entscheidend ist. Der Name der Methode ist v╨ñllig irrelevant. Es ist 
  1001.       insbesondere m╨ñglich, eine botschaftsverarbeitende Methode durch eine 
  1002.       Methode v╨ñllig anderen Namens zu ╨æberschreiben, solange nur die Nummern 
  1003.       ╨æbereinstimmen. 
  1004.  
  1005.       Enth╨ölt beim Aufruf von Dispatch der gesamte in Frage kommende Zweig der 
  1006.       Klassenhierarchie keine Methode mit der angegebenen Nummer, dann wird 
  1007.       eine virtuelle Methode DefaultHandler aufgerufen, die von der Basisklasse 
  1008.       TObject wie folgt bereitgestellt wird: 
  1009.  
  1010.             procedure DefaultHandler(var Message); virtual;
  1011.  
  1012.       Diese Methode tut ╨æberhaupt nichts. Es ist aber m╨ñglich, DefaultHandler 
  1013.       zu ╨æberschreiben, um ein anderes Standardverhalten bei unbehandelten 
  1014.       Nachrichten zu implementieren, zum Beispiel die Ausgabe einer 
  1015.       Fehlermeldung. 
  1016.  
  1017.       Die graphischen Bildschirmelemente der SPCC-Bibliothek ╨æberschreiben 
  1018.       diese Methode derart, da╤ü vom Objekt nicht behandelte Nachrichten an eine 
  1019.       Betriebssystem-Routine ╨æbergeben werden, die eine passende 
  1020.       Standard-Aktion f╨ær das entsprechende Bildschirmelement durchf╨æhrt. 
  1021.  
  1022.      Konstruktoren 
  1023.  
  1024.       Konstruktoren sind spezielle Methoden, deren Aufruf ein neues Objekt 
  1025.       erzeugt und initialisiert. 
  1026.  
  1027.       Konstruktoren werden bei Deklaration und Implementierung durch das 
  1028.       Schl╨æsselwort constructor eingeleitet. Ein Konstruktor darf eine 
  1029.       beliebige Liste formaler Parameter haben, aber keinen Wert zur╨æckliefern. 
  1030.       Er hat also die Gestalt einer Prozedurmethode. 
  1031.  
  1032.       Es gibt zwei Varianten, einen Konstruktor aufzurufen. Die eine entspricht 
  1033.       dem Aufruf einer gew╨ñhnlichen Methode auf einer Instanzvariablen, nur da╤ü 
  1034.       diese Variable vor dem Aufruf des Konstruktors noch kein g╨æltiges Objekt 
  1035.       referenziert. Es wird ein Objekt erzeugt und initialisiert, dessen Typ 
  1036.       dem der Instanzvariablen entspricht. Die Adresse dieses Objekts wird in 
  1037.       die Instanzvariable geschrieben. 
  1038.  
  1039.             type
  1040.               TCustomer = class(TObject)
  1041.               private
  1042.                 FName: PString;
  1043.               public
  1044.                 constructor Create(Name: string);
  1045.               end;
  1046.  
  1047.             constructor TCustomer.Create(Name: string);
  1048.             begin
  1049.               FName := NewStr(Name);
  1050.             end;
  1051.  
  1052.             var
  1053.               Customer: TCustomer;
  1054.  
  1055.             begin
  1056.               // Erzeuge eine Instanz von TCustomer.
  1057.  
  1058.               Customer.Create('Thomas Jefferson');
  1059.             end.
  1060.  
  1061.       Die andere Variante ben╨ñtigt die Angabe einer Klasse anstelle der 
  1062.       Instanzvariablen. Das Ergebnis dieses Aufrufes mu╤ü im Rahmen einer 
  1063.       Zuweisung an eine Instanzvariable ╨æbergeben werden. Bei dieser Variante 
  1064.       ist es m╨ñglich, Objekte zu erzeugen, deren Typ nicht exakt dem der 
  1065.       Variablen entspricht, sofern die Regeln f╨ær Zuweisungskompatibilit╨öt 
  1066.       eingehalten werden. 
  1067.  
  1068.             type
  1069.               TMailOrderCustomer = class(TCustomer)
  1070.               private
  1071.                 FAddress: PString;
  1072.               public
  1073.                 constructor Create(Name, Address: string);
  1074.               end;
  1075.  
  1076.             constructor TMailOrderCustomer.Create(Name, Address: string);
  1077.             begin
  1078.               inherited Create(Name);
  1079.               FAddress := NewStr(Address);
  1080.             end;
  1081.  
  1082.             var
  1083.               Customer1, Customer2: TCustomer;
  1084.  
  1085.             begin
  1086.               // Erzeuge eine Instanz von TCustomer.
  1087.  
  1088.               Customer1 := TCustomer.Create('Thomas Jefferson');
  1089.  
  1090.               // Erzeuge eine Instanz von TMailOrderCustomer. Da diese Klasse
  1091.               // zuweisungskompatibel zu TCustomer ist, kann Customer2 diese
  1092.               // Instanz referenzieren.
  1093.  
  1094.               Customer2 := TMailOrderCustomer.Create('George Washington',
  1095.                               'White-House, Washington, DC');
  1096.             end.
  1097.  
  1098.       Achtung: Bei Borland Delphi ist nur die zweite Variante m╨ñglich. Wenn 
  1099.       Programme entwickelt werden, deren Quellcode zwischen Speed-Pascal und 
  1100.       Delphi ausgetauscht werden soll, dann mu╤ü die erste Variante vermieden 
  1101.       werden, was aber keinerlei Einschr╨önkung der Funktionalit╨öt des Programms 
  1102.       darstellt. 
  1103.  
  1104.       Beim Aufruf eines Konstruktors werden automatisch folgende Aktionen 
  1105.       ausgef╨æhrt: 
  1106.  
  1107.         -  Der f╨ær die Objektinstanz ben╨ñtigte Speicher wird auf dem Heap 
  1108.            reserviert. Die Adresse des Speicherbereiches wird in die 
  1109.            Instanzvariable geschrieben, mit der Konstruktor aufgerufen wurde. 
  1110.  
  1111.         -  Der reservierte Speicherbereich wird mit Nullen gef╨ællt. Dadurch 
  1112.            erh╨ölt jedes Feld des neuen Objekts einen definierten Zustand. 
  1113.            Welcher Zustand dies ist, h╨öngt vom Typ des Feldes ab: 
  1114.  
  1115.              -- Ganzzahlen und Flie╤ükommazahlen erhalten den Wert Null. 
  1116.  
  1117.              -- Zeiger und Objektreferenzen erhalten den Wert nil. 
  1118.  
  1119.              -- Einzelne Zeichen erhalten das Nullzeichen Chr(0). 
  1120.  
  1121.              -- Strings erhalten die L╨önge Null. 
  1122.  
  1123.              -- Felder vom Typ Boolean erhalten den Wert False. 
  1124.  
  1125.              -- Bei strukturierten Feldern wie Records und Arrays gelten diese 
  1126.                 Regeln f╨ær alle Elemente. 
  1127.  
  1128.         -  Der Benutzercode des Konstruktors, also die Folge der Anweisungen 
  1129.            zwischen begin und end, wird ausgef╨æhrt. 
  1130.  
  1131.       Bei der Implementierung eines Konstruktors sollten die Schritte 
  1132.       ausgef╨æhrt werden, die n╨ñtig sind, um eine neue Instanz korrekt zu 
  1133.       initialisieren. 
  1134.  
  1135.       Es ist m╨ñglich, mit inherited den Konstruktor des Vorfahren aufzurufen. 
  1136.       Dabei wird nur der Benutzercode des geerbten Konstruktors ausgef╨æhrt, 
  1137.       nicht aber eine weitere Instanz erzeugt. Es ist ╨æblich, zuerst den 
  1138.       Konstruktor des Vorfahren aufzurufen, um die von Vorfahren geerbten 
  1139.       Fehler zu initialisieren. Im Anschlu╤ü werden meist die zus╨ötzlichen 
  1140.       Fehler der neuen Klasse initialisiert. 
  1141.  
  1142.       Eine Klasse, die keine Felder zus╨ötzlich zu denen ihres Vorfahren 
  1143.       deklariert oder deren Felder bei der Initialisierung alle auf Null 
  1144.       gesetzt werden m╨æssen, kommt eventuell ohne eigenen Konstruktor aus. Der 
  1145.       Konstruktor des Vorfahren, im Extremfall der von TObject, kann diese 
  1146.       Aufgabe ╨æbernehmen. 
  1147.  
  1148.       Wenn w╨öhrend des Konstruktoraufrufes an einer beliebigen Stelle eine 
  1149.       Exception ausgel╨ñst wird, dann wird zuerst zum Destruktor verzweigt, 
  1150.       bevor die Exception-Behandlungsroutine angesprungen oder ein 
  1151.       Laufzeitfehler ausgel╨ñst wird. Deshalb ist es notwendig, da╤ü der 
  1152.       Destruktor auf diesen Fall reagieren kann, also auch in der Lage ist, nur 
  1153.       teilweise initialisierte Objekte zu zerst╨ñren. 
  1154.  
  1155.       Konstruktoren k╨ñnnen virtuell sein. Dadurch wird polymorphes Erzeugen von 
  1156.       Objekten m╨ñglich, also von Objekten, deren exakter Typ zur Zeit der 
  1157.       Compilierung noch nicht bekannt ist. Ein virtueller Konstruktor mu╤ü immer 
  1158.       in der Zuweisungsvariante aufgerufen werden. Genaueres dazu befindet sich 
  1159.       im Abschnitt ╨æber Metaklassen. 
  1160.  
  1161.      Destruktoren 
  1162.  
  1163.       Destruktoren sind spezielle Methoden, deren Aufruf ein Objekt zerst╨ñrt. 
  1164.  
  1165.       Destruktoren werden bei Deklaration und Implementierung durch das 
  1166.       Schl╨æsselwort destructor eingeleitet. Ein Destruktor darf eine beliebige 
  1167.       Liste formaler Parameter haben, was aber ╨æblicherweise nicht der Fall 
  1168.       ist. Ein Destruktor darf keinen Wert zur╨æckliefern, hat also die Gestalt 
  1169.       einer Prozedurmethode. 
  1170.  
  1171.       Destruktoren sollten virtuell sein, damit sichergestellt ist, da╤ü zur 
  1172.       Laufzeit der zur Instanz passende Destruktor aufgerufen wird. Jede Klasse 
  1173.       erbt von TObject einen virtuellen, parameterlosen Destruktor Destroy. Es 
  1174.       wird empfohlen, da╤ü Sie diesen Destruktor in Ihren eigenen Klassen mit 
  1175.       override ╨æberschreiben. 
  1176.  
  1177.       Ein Destruktor wird auf die gleiche Weise aufgerufen wie eine gew╨ñhnliche 
  1178.       Methode. Er f╨æhrt zuerst den Benutzercode, also die Anweisungsfolge 
  1179.       zwischen begin und end aus, dann gibt er den von der Instanz ben╨ñtigten 
  1180.       Speicher auf dem Heap frei. 
  1181.  
  1182.       Es ist m╨ñglich, innerhalb eines Destruktors mit inherited auf den 
  1183.       Destruktor des Vorfahren zuzugreifen. In diesem Fall wird nur der 
  1184.       Benutzercode des geerbten Destruktors ausgef╨æhrt, die Instanz wird aber 
  1185.       erst beim Beenden des ╨æbergeordneten Destruktoraufrufes zerst╨ñrt. 
  1186.  
  1187.             type
  1188.               TCustomer = class(TObject)
  1189.               private
  1190.                 FName: PString;
  1191.               public
  1192.                 constructor Create(Name: string);
  1193.                 destructor Destroy; override;
  1194.               end;
  1195.  
  1196.             constructor TCustomer.Create(Name: string);
  1197.             begin
  1198.               FName := NewStr(Name);
  1199.             end;
  1200.  
  1201.             destructor TCustomer.Destroy;
  1202.             begin
  1203.               DisposeStr(FName);
  1204.             end;
  1205.  
  1206.             var
  1207.               Customer: TCustomer;
  1208.  
  1209.             begin
  1210.               // Erzeuge eine Instanz.
  1211.  
  1212.               Customer.Create('Thomas Jefferson');
  1213.  
  1214.               // Zerst╨ñre die Instanz wieder.
  1215.  
  1216.               Customer.Destroy;
  1217.             end.
  1218.  
  1219.       Eine Klasse, die keine Felder zus╨ötzlich zu denen ihres Vorfahren 
  1220.       deklariert oder deren Felder nur einfache, nicht-verzeigerte Strukturen 
  1221.       enthalten, ben╨ñtigt m╨ñglicherweise keine speziellen Aufr╨öumaktionen zum 
  1222.       Zerst╨ñren des Objekts. In diesem Fall kann der Destruktor des Vorfahren 
  1223.       benutzt werden, und es mu╤ü kein eigener Destruktor deklariert werden. Ob 
  1224.       dies so ist, m╨æssen Sie von Fall zu Fall entscheiden. 
  1225.  
  1226.       Wenn w╨öhrend eines Konstruktoraufrufes eine Exception auftritt, dann wird 
  1227.       zuerst zum Destruktor verzweigt, bevor die Exception-Behandlungsroutine 
  1228.       angesprungen oder ein Laufzeitfehler ausgel╨ñst wird. Deshalb ist es 
  1229.       notwendig, da╤ü ein Destruktor auf diesen Fall reagieren kann, also auch 
  1230.       in der Lage ist, nur teilweise initialisierte Objekte zu zerst╨ñren. 
  1231.  
  1232.       Das ist insbesondere wichtig, wenn das Objekt ╨æber Felder von Zeiger- 
  1233.       oder Objekttypen verf╨ægt. Der Destruktor sollte diese Felder auf nil 
  1234.       pr╨æfen, bevor er versucht, die zugeh╨ñrigen Strukturen freizugeben. 
  1235.  
  1236.       Das Zerst╨ñren eines Objektes kann sicherer gestaltet werden, wenn statt 
  1237.       des Destruktors die Methode Free aufgerufen wird, die alle Klassen von 
  1238.       TObject erben. Free pr╨æft, ob die Instanz den Wert Nil enth╨ölt, und ruft 
  1239.       nur dann den Destruktor Destroy auf, wenn das nicht der Fall ist. 
  1240.  
  1241.      Klassenmethoden 
  1242.  
  1243.       Klassenmethoden sind Prozedur- oder Funktionsmethoden, denen bei 
  1244.       Deklaration und Implementierung zus╨ötzlich das Schl╨æsselwort class 
  1245.       vorangestellt wird. 
  1246.  
  1247.       Sie k╨ñnnen virtuell sein, d╨ærfen dann aber wieder nur durch 
  1248.       Klassenmethoden ╨æberschrieben werden. Die Regeln sind hierbei die 
  1249.       gleichen, die auch bei gew╨ñhnlichen virtuellen Methoden gelten. 
  1250.  
  1251.             type
  1252.               TConfigFile = class
  1253.                 ...
  1254.                 class function GetDefaultName: string;
  1255.                 ...
  1256.               end;
  1257.  
  1258.       Eine Klassenmethode kann sowohl auf einem Objekt als auch auf einer 
  1259.       Klasse operieren. Damit stehen Klassenmethoden auch dann zur Verf╨ægung, 
  1260.       wenn keine einzige Instanz einer Klasse existiert. 
  1261.  
  1262.             begin
  1263.               WriteLn(TConfigFile.GetDefaultName);
  1264.             end.
  1265.  
  1266.       Innerhalb der Implementierung einer Klassenmethode darf au╤üer auf globale 
  1267.       Bezeichner nur auf andere Klassenmethoden zugegriffen werden. Ein Zugriff 
  1268.       auf Felder, Eigenschaften oder gew╨ñhnliche Methoden der Klasse wird vom 
  1269.       Compiler unterbunden. Der auch in Klassenmethoden vorhandene implizite 
  1270.       Parameter Self enth╨ölt keine Objektreferenz, sondern eine Referenz auf 
  1271.       die Klasse, f╨ær die die Methode tats╨öchlich aufgerufen wurde. Beim Aufruf 
  1272.       der Klassenmethode auf einer Instanz enth╨ölt Self den tats╨öchlichen Typ 
  1273.       dieser Instanz. 
  1274.  
  1275.       Klassenmethoden sind dazu gedacht, bestimmte Prozeduren oder Funktionen 
  1276.       einer Klasse auch dann verf╨ægbar zu machen, wenn keine Instanz der Klasse 
  1277.       existiert. Dabei handelt es sich ╨æblicherweise um Methoden, die auf 
  1278.       irgendeine Weise Informationen ╨æber die Klasse liefern. 
  1279.  
  1280.       TObject vererbt seinen Nachkommen eine Reihe von Klassenmethoden, mit 
  1281.       denen zum Beispiel der Name einer Klasse ermittelt werden kann, der Name 
  1282.       des Moduls, in dem die Klasse deklariert wurde, oder die Gr╨ñ╤üe einer 
  1283.       Instanz der Klasse. N╨öheres dazu entnehmen Sie der Beschreibung der 
  1284.       Klasse TObject. 
  1285.  
  1286.  
  1287. ΓòÉΓòÉΓòÉ 1.7. Eigenschaften ΓòÉΓòÉΓòÉ
  1288.  
  1289.  ΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûä
  1290.  Eigenschaften
  1291.  ΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇ
  1292.  
  1293. Was sind Eigenschaften? 
  1294.  
  1295. Eigenschaften sind benannte Attribute eines Objekts. 
  1296.  
  1297. Sie stellen sich dem Benutzer ╨öhnlich wie Felder dar, da sie ╨æber einen Typ 
  1298. verf╨ægen und ihr Wert in Form einer Zuweisung ge╨öndert wird. Die M╨ñglichkeiten 
  1299. von Eigenschaften gehen aber ╨æber die von Feldern weit hinaus, da es m╨ñglich 
  1300. ist, sowohl den lesenden als auch den schreibenden Zugriff auf die Eigenschaft 
  1301. einzeln zu kontrollieren oder zu verbieten. 
  1302.  
  1303. Jeder der beiden m╨ñglichen Zugriffsarten einer Eigenschaft liegt entweder ein 
  1304. Feld oder eine Methode zugrunde. Im ersten Fall wird der Wert der Eigenschaft 
  1305. aus dem Feld gelesen oder in dieses geschrieben. Im zweiten Fall wird durch das 
  1306. Lesen oder Schreiben der Eigenschaft implizit die Methode aufgerufen, so da╤ü 
  1307. durch eine einfache Zuweisung komplexe Operationen in Gang gesetzt werden 
  1308. k╨ñnnen. 
  1309.  
  1310. Es ist m╨ñglich, indizierte Eigenschaften zu deklarieren, die f╨ær den Benutzer 
  1311. die Gestalt eines Arrays haben. Da beiden Zugriffsarten einer indizierten 
  1312. Eigenschaft immer eine Methode zugrunde liegt, kann sie im Gegensatz zu 
  1313. gew╨ñhnlichen Arrays ╨æber beliebige Typen indiziert werden. 
  1314.  
  1315. Eine indizierte Eigenschaft kann zur voreingestellten Eigenschaft erkl╨ört 
  1316. werden, so da╤ü sich das gesamte Objekt dem Benutzer als Array darstellt. Es ist 
  1317. in diesem Fall nicht mehr notwendig, bei einem Zugriff auf die Eigenschaft 
  1318. deren Bezeichner anzugeben. 
  1319.  
  1320. F╨ær Eigenschaften, die als published gekennzeichnet werden, erzeugt der 
  1321. Compiler spezielle Informationen, die zur Laufzeit des Programms oder f╨ær die 
  1322. Zusammenarbeit mit dem Objekt-Inspektor der Sibyl-Umgebung von Bedeutung sind. 
  1323. Das Verhalten einer Eigenschaft in diesem Kontext kann mit einigen speziellen 
  1324. Schl╨æsselw╨ñrtern kontrolliert werden. 
  1325.  
  1326. Deklarieren von Eigenschaften 
  1327.  
  1328. Eigenschaften werden auf die folgende Weise deklariert: 
  1329.  
  1330. <Syntaxdiagramm: Properties> 
  1331.  
  1332. Die Deklaration einer Eigenschaft wird durch das Schl╨æsselwort property 
  1333. eingeleitet, gefolgt vom Bezeichner der Eigenschaft und von deren Typ. Es 
  1334. folgen in beliebiger Reihenfolge die Definitionen dessen, was bei lesendem oder 
  1335. schreibendem Zugriff auf die Eigenschaft geschieht. Die Definition der mit dem 
  1336. Lesen der Eigenschaft assoziierten Aktion wird eingeleitet durch das 
  1337. Schl╨æsselwort read, die der schreibenden Aktion analog durch write. 
  1338.  
  1339. Wenn eine der beiden Aktionen nicht definiert wird, dann existiert die 
  1340. entsprechende Zugriffsart nicht. Der Versuch, den Wert einer nur zum Lesen 
  1341. freigegebenen Eigenschaft zu ╨öndern, wird vom Compiler ebenso abgewiesen wie 
  1342. der Versuch, eine nur zum Schreiben freigegebene Eigenschaft in einem Ausdruck 
  1343. als Wert einzusetzen und damit implizit auszulesen. 
  1344.  
  1345. Sowohl das Lesen als auch das Schreiben einer Eigenschaft kann entweder mit 
  1346. einem Feld oder mit einer Methode assoziiert werden. 
  1347.  
  1348. Wenn das Lesen mit einem Feld assoziiert ist, dann wird beim Einsetzen der 
  1349. Eigenschaft in einen Ausdruck der Wert des Feldes herangezogen. Wenn das 
  1350. Schreiben mit einem Feld assoziiert ist, dann wird beim Zuweisen eines Wertes 
  1351. an die Eigenschaft dieser Wert in das entsprechende Feld geschrieben. In beiden 
  1352. F╨öllen mu╤ü das Feld vom gleichen Typ sein wie die Eigenschaft. 
  1353.  
  1354. Wird das Lesen einer einfachen Eigenschaft mit einer Methode assoziiert, so mu╤ü 
  1355. die Methode eine parameterlose Funktion sein, deren Ergebnistyp dem Typ der 
  1356. Eigenschaft entspricht. Der Compiler ersetzt jede Benutzung der Eigenschaft in 
  1357. einem Ausdruck durch einen Aufruf der Methode und bezieht das Funktionsergebnis 
  1358. dann in den Ausdruck ein. 
  1359.  
  1360. Wird das Schreiben einer einfachen Eigenschaft mit einer Methode assoziiert, so 
  1361. mu╤ü diese Methode eine Prozedur sein, deren einziger Parameter dem Typ der 
  1362. Eigenschaft entspricht. Der Compiler ersetzt jede ╨₧nderung des Wertes der 
  1363. Eigenschaft in Form einer Zuweisung durch einen Aufruf der Methode, wobei er 
  1364. den neuen Wert der Eigenschaft als aktuellen Parameter der Methode einsetzt. 
  1365.  
  1366. Die Methoden, die einer Eigenschaft zugrundeliegen, erhalten in Speed-Pascal 
  1367. ╨æblicherweise einen Bezeichner, der dem Bezeichner der Eigenschaft entspricht, 
  1368. wobei der lesenden Methode ein Get und der schreibenden ein Set vorangestellt 
  1369. wird. Sowohl Felder als auch Methoden, die einer Eigenschaft zugrundeliegen, 
  1370. sind meist private. 
  1371.  
  1372. Folgendes Beispiel demonstriert die Arbeit mit einer Eigenschaft, die auf zwei 
  1373. Methoden basiert. 
  1374.  
  1375. type
  1376.   TCustomer = class(TObject)
  1377.   private
  1378.     FName: PString;
  1379.     FID: Integer;
  1380.     function GetName: string;
  1381.     procedure SetName(const S: string);
  1382.   public
  1383.     constructor Create(Name: string);
  1384.     destructor Destroy; override;
  1385.  
  1386.     property ID: Integer           // Auf diese Eigenschaft kann nur lesend
  1387.       read FID;                    // zugegriffen werden. Sie liefert den
  1388.                                    // Wert des Feldes FID.
  1389.  
  1390.     property Name: string          // Auf diese Eigenschaft kann lesend und
  1391.       read GetName write SetName;  // schreibend zugegriffen werden. Sie
  1392.                                    // ruft implizit die Methoden GetName
  1393.                                    // und SetName auf.
  1394.   end;
  1395.  
  1396.   ...
  1397.  
  1398. function TCustomer.GetName: string;
  1399. begin
  1400.   Result := FName^;
  1401. end;
  1402.  
  1403. procedure TCustomer.SetName(const S: string);
  1404. begin
  1405.   AssignStr(FName, S);
  1406. end;
  1407.  
  1408. var
  1409.   Customer: TCustomer;
  1410.  
  1411. begin
  1412.   ...
  1413.   with Customer do
  1414.   begin
  1415.     WriteLn('ID:   ', ID);   // Liest implizit das Feld FID aus.
  1416.     WriteLn('Name: ', Name); // Ruft implizit die Funktion GetName auf.
  1417.   end;
  1418.   ...
  1419. end.
  1420.  
  1421. Zugriff auf Eigenschaften 
  1422.  
  1423. Der Zugriff auf Eigenschaften eines Objekts entspricht aus der Sicht des 
  1424. Benutzers dem Zugriff auf Felder. 
  1425.  
  1426. Der Wert der Eigenschaft wird gelesen, indem die Eigenschaft in Ausdr╨æcken 
  1427. eingesetzt wird. Eine Eigenschaft erh╨ölt einen neuen Wert durch eine Zuweisung. 
  1428. Falls einer der beiden Zugriffsarten eine Methode zugrunde liegt, wird diese an 
  1429. den entsprechenden Stellen des Programms automatisch aufgerufen. 
  1430.  
  1431. Da Eigenschaften nicht notwendigerweise tats╨öchlich vorhandene Felder 
  1432. zugrundeliegen, kann der Operator @ nicht benutzt werden, um die Adresse einer 
  1433. Eigenschaft zu ermitteln. Ebenso ist es nicht m╨ñglich, eine Eigenschaft als 
  1434. aktuellen Parameter an eine Prozedur oder Funktion zu ╨æbergeben, die dort einen 
  1435. var-Parameter erwartet. Der Compiler f╨öngt diese Fehler ab. 
  1436.  
  1437. Indizierte Eigenschaften 
  1438.  
  1439. Eine indizierte Eigenschaft stellt sich dem Benutzer wie ein Array dar. 
  1440.  
  1441. Bei der Deklaration einer indizierten Eigenschaft wird zwischen ihrem 
  1442. Bezeichner und ihrem Typ in eckigen Klammern eine beliebige Liste von formalen 
  1443. Parametern angegeben, ╨æber die die Eigenschaft indiziert wird. Dabei ist jeder 
  1444. Typ erlaubt, der in der formalen Parameterliste einer Prozedur erlaubt ist; 
  1445. indizierte Eigenschaften sind nicht wie Arrays auf Aufz╨öhlungstypen beschr╨önkt. 
  1446.  
  1447. Die mit dem Lesen und Schreiben einer indizierten Eigenschaft assoziierten 
  1448. Aktionen m╨æssen Methoden sein. Sie werden auf die gleiche Weise angegeben wie 
  1449. bei einfachen Eigenschaften, aber sie m╨æssen besondere Bedingungen erf╨ællen: 
  1450.  
  1451.      Die mit dem Lesen der Eigenschaft assoziierte Methode mu╤ü eine Funktion 
  1452.       sein. Ihre formale Parameterliste mu╤ü der in eckigen Klammern angegebenen 
  1453.       Parameterliste der Eigenschaft entsprechen. Der Typ des 
  1454.       Funktionsergebnisses mu╤ü dem Typ der Eigenschaft entsprechen. 
  1455.  
  1456.      Die mit dem Schreiben der Eigenschaft assoziierte Methode mu╤ü eine 
  1457.       Prozedur sein. Ihre formale Parameterliste mu╤ü der in eckigen Klammern 
  1458.       angegebenen Parameterliste der Eigenschaft entsprechen. Zus╨ötzlich mu╤ü 
  1459.       sie einen weiteren Parameter am Ende ihrer Parameterliste besitzen, 
  1460.       dessen Typ mit dem Typ der Eigenschaft ╨æbereinstimmt. 
  1461.  
  1462.   type
  1463.     TStrings = class(TObject)
  1464.     protecedD
  1465.       function GetValue(const Name: string): string; virtual;
  1466.       procedure SetValue(const Name, Value: string); virtual;
  1467.       ...
  1468.     public
  1469.       property Values[const Name: string]: string
  1470.         read GetValue write SetValue;
  1471.     end;
  1472.  
  1473.     ...
  1474.  
  1475.   var
  1476.     MyStrings: TStrings;
  1477.  
  1478.   begin
  1479.     ...
  1480.     MyStrings.Values['Compiler'] := 'Speed-Pascal/2 Version 2.0';
  1481.     WriteLn(MyStrings.Values['Compiler']);
  1482.     ...
  1483.   end.
  1484.  
  1485.  Indizierte Eigenschaften d╨ærfen nicht als published gekennzeichnet werden, 
  1486.  weil der Compiler f╨ær sie keine Laufzeitinformationen erzeugen kann. 
  1487.  
  1488.  Voreingestellte Eigenschaften 
  1489.  
  1490.  Es ist m╨ñglich, eine indizierte Eigenschaft zur voreingestellten Eigenschaft 
  1491.  der Klasse zu erkl╨ören. Dies geschieht durch Anh╨öngen des Schl╨æsselwortes 
  1492.  default an die Deklaration der Eigenschaft. 
  1493.  
  1494.  Auf eine voreingestellte Eigenschaft kann zugegriffen werden, ohne da╤ü der 
  1495.  Bezeichner der Eigenschaft angegeben werden mu╤ü. Der gew╨ænschte Index der 
  1496.  Eigenschaft folgt in eckigen Klammern und ohne Punkt unmittelbar auf den 
  1497.  Bezeichner der Instanzvariablen. Damit stellt sich dem Benutzer das gesamte 
  1498.  Objekt wie ein Array dar. Er kann jedoch weiterhin auf alle Komponenten des 
  1499.  Objektes ╨æber deren Bezeichner zugreifen. 
  1500.  
  1501.   type
  1502.     TStrings = class(TObject)
  1503.     protected
  1504.       function Get(Index: LongInt): string; virtual; abstract;
  1505.       procedure Put(Index: LongInt; const S: string); virtual; abstract;
  1506.       ...
  1507.     public
  1508.       property Strings[Index: LongInt]: string read Get write Put; default;
  1509.       ...
  1510.     end;
  1511.  
  1512.     ...
  1513.  
  1514.   var
  1515.     MyStrings: TStrings;
  1516.  
  1517.   begin
  1518.     ...
  1519.     MyStrings[1] := 'Speed-Pascal/2 Version 2.0';
  1520.     WriteLn(MyStrings[1]);
  1521.     ...
  1522.   end.
  1523.  
  1524.  Eine Klasse kann nur eine voreingestellte Eigenschaft besitzen. Die 
  1525.  Voreinstellung einer Eigenschaft vererbt sich an Nachfahren, so da╤ü die 
  1526.  Eigenschaft auch dort voreingestellt ist und bleibt. Auch die Sichtbarkeit 
  1527.  einer voreingestellten Eigenschaft kann in Nachfahren nicht ge╨öndert werden. 
  1528.  
  1529.  Beachten Sie, da╤ü der Angabe von default zum Festlegen einer voreingestellten 
  1530.  Eigenschaft ein Semikolon vorangeht, im Gegensatz zum Festlegen des 
  1531.  Standardwertes einer Eigenschaft im Objekt-Inspektor, der ebenfalls mit dem 
  1532.  Schl╨æsselwort default, aber ohne Semikolon angegeben wird. 
  1533.  
  1534.  Gemeinsame Zugriffsmethoden 
  1535.  
  1536.  Das Schl╨æsselwort index wird derzeit nicht unterst╨ætzt. 
  1537.  
  1538.  Eigenschaften und Laufzeitinformationen 
  1539.  
  1540.  Die Schl╨æsselw╨ñrter default, nodefault und stored werden derzeit nicht 
  1541.  unterst╨ætzt. 
  1542.  
  1543.  
  1544. ΓòÉΓòÉΓòÉ 1.8. Metaklassen ΓòÉΓòÉΓòÉ
  1545.  
  1546.  ΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûä
  1547.  Metaklassen
  1548.  ΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇ
  1549.  
  1550. Was sind Metaklassen? 
  1551.  
  1552. Eine Metaklasse ist ein Datentyp, dessen Werte Klassen sind. 
  1553.  
  1554. ╨₧hnlich wie eine Klasse einen Typ definiert, der Objektreferenzen aufnehmen 
  1555. kann, kann eine Variable vom Typ einer Metaklasse Referenzen auf Klassen 
  1556. enthalten. Deshalb werden Metaklassen auch als Klassenreferenztypen bezeichnet. 
  1557.  
  1558. Der Wertebereich einer Metaklasse umfa╤üt die Klasse, f╨ær die sie deklariert 
  1559. wurde, und alle deren Nachfahren, insbesondere auch jene, die erst zu einem 
  1560. sp╨öteren Zeitpunkt deklariert werden. Einer Variablen vom Typ einer Metaklasse 
  1561. k╨ñnnen also genau die Klassen als Werte zugewiesen werden, die mit der Klasse 
  1562. zuweisungskompatibel sind, f╨ær die die Metaklasse deklariert wurde. 
  1563.  
  1564. Metaklassen k╨ñnnen ╨æberall dort im Programm eingesetzt werden, wo auch direkt 
  1565. mit Klassen operiert wird. Das betrifft insbesondere den Aufruf von 
  1566. Klassenmethoden, das Pr╨æfen und Wandeln von Typen mit den Operatoren is und as, 
  1567. sowie das polymorphe Konstruieren von Objekten. In allen F╨öllen mu╤ü die 
  1568. tats╨öchliche Klasse nicht bereits zur Zeit der Compilierung feststehen, sondern 
  1569. es wird die Klasse benutzt, die zur Laufzeit als Wert der Variablen vorgefunden 
  1570. wird. 
  1571.  
  1572. Deklarieren von Metaklassen 
  1573.  
  1574. Metaklassen werden auf die folgende Weise deklariert: 
  1575.  
  1576. <Syntaxdiagramm: Metaclasses> 
  1577.  
  1578. Eine Metaklasse wird mit den Schl╨æsselw╨ñrtern class of deklariert. Die Klasse, 
  1579. zu der die Metaklasse geh╨ñrt, mu╤ü bereits deklariert sein, zumindestens mit 
  1580. einer forward-Deklaration. 
  1581.  
  1582. type
  1583.   TVehicle = class
  1584.     ...
  1585.   end;
  1586.  
  1587.   TVehicleClass = class of TVehicle;
  1588.  
  1589. Die Unit System deklariert bereits eine Metaklasse TClass als class of TObject. 
  1590.  
  1591. Benutzen von Metaklassen 
  1592.  
  1593. Variablen vom Typ einer Metaklasse k╨ñnnen als Werte alle Klassen aufnehmen, die 
  1594. mit der Klasse, f╨ær die die Metaklasse deklariert wurde, zuweisungskompatibel 
  1595. sind. Zus╨ötzlich kann einer solchen Variablen der Wert nil zugewiesen werden, 
  1596. um anzudeuten, da╤ü die Variable momentan keine g╨æltige Klasse referenziert. 
  1597.  
  1598. type
  1599.   TVehicle = class(TObject);
  1600.     ...
  1601.   end;
  1602.  
  1603.   TShip = class(TVehicle)
  1604.     ...
  1605.   end;
  1606.  
  1607.   TVehicleClass = class of TVehicle;
  1608.  
  1609. var
  1610.   AllowedVehicles: TVehicleClass;
  1611.  
  1612. begin
  1613.   ...
  1614.   AllowedVehicles := TVehicle;
  1615.   ...
  1616.   AllowedVehicles := TShip;
  1617.   ...
  1618. end.
  1619.  
  1620. Variablen vom Typ einer Metaklasse k╨ñnnen ╨æberall dort im Programm eingesetzt 
  1621. werden, wo auch direkt mit Klassen operiert wird. Insbesondere k╨ñnnen sie auf 
  1622. der rechten Seite eines der Operatoren is und as auftauchen, bei Aufruf von 
  1623. Klassenmethoden und beim Konstruieren von Objekten. 
  1624.  
  1625.      Metaklassen und Klassenoperatoren 
  1626.  
  1627.       Metaklassen k╨ñnnen auf der rechten Seite eines Ausdrucks benutzt werden, 
  1628.       der mit den Operatoren is und as gebildet wird. Es gelten dabei 
  1629.       prinzipiell die gleichen Regeln wie bei der direkten Ang 
  1630.  
  1631.      Metaklassen und Klassenmethoden 
  1632.  
  1633.       Metaklassen k╨ñnnen benutzt werden, um eine Klassenmethode aufzurufen. Der 
  1634.       entsprechende Variablenbezeichner wird dabei gefolgt von einem Punkt vor 
  1635.       den Methodenbezeichner gesetzt, analog zum Aufruf der Methode ╨æber einen 
  1636.       Klassenbezeichner. Der tats╨öchliche Typ der Klasse steht dann nicht 
  1637.       bereits zur Zeit der Compilierung fest, sondern wird erst zur Laufzeit 
  1638.       der Variablen entnommen. Es wird die Klassenmethode aufgerufen, die dem 
  1639.       tats╨öchlichen Wert der Klassenreferenz entsricht. 
  1640.  
  1641.       Achten Sie darauf, da╤ü Klassenmethoden, die Sie auf diese Weise benutzen 
  1642.       wollen, als virtuell gekennzeichnet sind. Ansonsten findet die Bindung 
  1643.       wie gewohnt bereits zur Zeit der Compilierung statt. Es wird dann stets 
  1644.       die Methode der Klasse aufgerufen, zu der die Metaklasse der Variablen 
  1645.       deklariert wurde. 
  1646.  
  1647.      Metaklassen und Konstruktoren 
  1648.  
  1649.       Metaklassen k╨ñnnen beim Aufruf eines Konstruktors zum Erzeugen eines 
  1650.       neuen Objekts benutzt werden. Bedingung daf╨ær ist, da╤ü die 
  1651.       Zuweisungsvariante des Konstruktoraufrufes gew╨öhlt wird, da die einfache 
  1652.       Variante nur die Angabe einer Instanzvariablen, nicht aber einer Klasse 
  1653.       erlaubt. 
  1654.  
  1655.       Diese Art des Aufrufes von Konstruktoren erm╨ñglicht das polymorphe 
  1656.       Konstruieren von Objekten, also von Objekten, deren tats╨öchlicher Typ 
  1657.       nicht bereits zur Zeit der Compilierung feststeht. Die Klasse, von der 
  1658.       die neue Instanz erzeugt wird, wird zur Laufzeit der Variablen entnommen. 
  1659.  
  1660.       Achten Sie darauf, da╤ü Konstruktoren, die Sie zum polymorphen 
  1661.       Konstruieren von Objekten benutzen wollen, als virtuell gekennzeichnet 
  1662.       sind. Ansonsten findet die Bindung wie gewohnt bereits zur Zeit der 
  1663.       Compilierung statt. Es wird dann stets eine Instanz der Klasse erzeugt, 
  1664.       zu der die Metaklasse der Variablen deklariert wurde. 
  1665.  
  1666.   type
  1667.     TVehicle = class
  1668.       constructor Create; virtual;
  1669.     end;
  1670.  
  1671.     TShip = class(TVehicle)
  1672.       constructor Create; override;
  1673.     end;
  1674.  
  1675.     TVehicleClass = class of TVehicle;
  1676.  
  1677.   var
  1678.     VehicleType: TVehicleClass;
  1679.     MyVehicle:   TVehicle;
  1680.  
  1681.   begin
  1682.     ...
  1683.     VehicleType := TShip;
  1684.     MyVehicle := TVehicleType.Create;
  1685.     ...
  1686.   end.
  1687.  
  1688.  
  1689. ΓòÉΓòÉΓòÉ 1.9. Vordefinierte Klassen ΓòÉΓòÉΓòÉ
  1690.  
  1691.  ΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûä
  1692.  Vordefinierte Klassen
  1693.  ΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇ
  1694.  
  1695. TObject und TClass 
  1696.  
  1697. Die in der Unit System deklarierte Klasse TObject ist die Basis der 
  1698. Objekthierarchie von Speed-Pascal. TObject besitzt rudiment╨öre Konstruktoren 
  1699. und Destruktoren sowie eine Reihe von Methoden, die f╨ær die Zusammenarbeit von 
  1700. Objekten mit der Sibyl-Umgebung wichtig sind. 
  1701.  
  1702. TObject ist letztlich Vorfahr jeder anderen Klasse. Wenn bei der Deklaration 
  1703. einer neuen Klasse nicht explizit ein Vorfahr angegeben wird, dann nimmt der 
  1704. Compiler TObject als Vorfahren an. Damit ist sichergestellt, da╤ü alle Objekte 
  1705. auf eine gemeinsame Basis zur╨æckgreifen k╨ñnnen. 
  1706.  
  1707. TClass ist die Metaklasse von TObject. Da alle anderen Klassen aufgrund ihrer 
  1708. Abstammung zuweisungskompatibel zu TObject sind, kann eine Variable vom Typ 
  1709. TClass als Werte s╨ömtliche Klassen aufnehmen, die jemals mit Speed-Pascal 
  1710. deklariert werden. 
  1711.  
  1712. Deklaration von TObject und TClass 
  1713.  
  1714. Die Klasse TObject ist zusammen mit ihrer Metaklasse TClass in der Unit System 
  1715. auf die folgende Weise deklariert: 
  1716.  
  1717. type
  1718.  
  1719.   TObject = CLASS;
  1720.  
  1721.   TClass  = CLASS OF TObject;
  1722.  
  1723.   TObject = CLASS
  1724.     CONSTRUCTOR Create;
  1725.     DESTRUCTOR Destroy; VIRTUAL;
  1726.     PROCEDURE Free;
  1727.     CLASS FUNCTION NewInstance: TObject; VIRTUAL;
  1728.     PROCEDURE FreeInstance; VIRTUAL;
  1729.     CLASS FUNCTION InitInstance(Instance: Pointer): TObject;
  1730.     CLASS FUNCTION ClassType: TClass;
  1731.     CLASS FUNCTION ClassName: STRING;
  1732.     CLASS FUNCTION ClassUnit: STRING;
  1733.     CLASS FUNCTION ClassParent: TClass;
  1734.     CLASS FUNCTION GetClassInfo: POINTER;
  1735.     CLASS FUNCTION InstanceSize: LONGWORD;
  1736.     CLASS FUNCTION InheritsFrom(AClass: TClass): BOOLEAN;
  1737.     PROCEDURE DefaultHandler(VAR Message); VIRTUAL;
  1738.     PROCEDURE DefaultFrameHandler(VAR Message); VIRTUAL;
  1739.     PROCEDURE Dispatch(VAR Message);
  1740.     PROCEDURE DispatchCommand(VAR Message;Command:LONGWORD);
  1741.     PROCEDURE FrameDispatch(VAR Message);
  1742.     CLASS FUNCTION MethodAddress(CONST Name: STRING): POINTER;
  1743.     CLASS FUNCTION MethodName(Address: POINTER): STRING;
  1744.     FUNCTION FieldAddress(Name: STRING): POINTER;
  1745.   END;
  1746.  
  1747. Methoden von TObject 
  1748.  
  1749. Viele Methoden von TObject werden entweder intern vom Laufzeitsystem ben╨ñtigt 
  1750. oder dienen zum Austausch von Informationen mit der visuellen 
  1751. Entwicklungsumgebung Sybil und der SPCC-Bibliothek. Eine Reihe von Methoden, 
  1752. unter anderem Konstruktor, Destruktor und die Methoden zur 
  1753. Botschaftsverarbeitung, k╨ñnnen und sollen vom Benutzer verwendet werden. 
  1754.  
  1755.      CONSTRUCTOR Create; 
  1756.  
  1757.       Der Konstruktor Create erzeugt eine neue, leere Instanz von TObject und 
  1758.       f╨ællt sie durch einen Aufruf von InitInstance mit Nullbytes. 
  1759.  
  1760.       In Nachfahren von TObject m╨æssen Sie den Konstruktor mit hoher 
  1761.       Wahrscheinlichkeit ╨æberschreiben, um zus╨ötzliche Felder des Objektes 
  1762.       korrekt zu initialisieren. Wenn bei der Initialisierung alle Felder auf 
  1763.       Null gesetzt werden, oder die neue Klasse keine Felder besitzt, dann kann 
  1764.       auch der Konstruktor von TObject diese Aufgabe ╨æbernehmen. 
  1765.  
  1766.      DESTRUCTOR Destroy; VIRTUAL; 
  1767.  
  1768.       Der Destruktor Destroy zerst╨ñrt die Instanz und gibt den von ihr belegten 
  1769.       Speicher auf dem Heap frei. 
  1770.  
  1771.       Wenn in einem Nachfahren von TObject keine weiteren Aktionen zum 
  1772.       Zerst╨ñren einer Instanz notwendig sind, dann kann der Destruktor von 
  1773.       TObject auch als Destruktor f╨ær diese Klasse benutzt werden. Wenn die 
  1774.       Klasse komplexe Unterstrukturen besitzt, die aufger╨öumt werden m╨æssen, 
  1775.       dann ben╨ñtigt die Klasse einen eigenen Destruktor. 
  1776.  
  1777.       Es wird empfohlen, da╤ü jede Klasse, die einen Destruktor ben╨ñtigt, 
  1778.       Destroy prinzipiell als parameterlosen Destruktor beibeh╨ölt und mittels 
  1779.       override ╨æberschreibt. 
  1780.  
  1781.      PROCEDURE Free; 
  1782.  
  1783.       Die Methode Free pr╨æft eine Instanz auf nil und ruft genau dann den 
  1784.       Destruktor Destroy auf, wenn der Wert der Instanz nicht nil ist, die 
  1785.       Variable also ein g╨æltiges Objekt referenziert. 
  1786.  
  1787.       Benutzen Sie Free, um mehr Sicherheit beim Zerst╨ñren eines Objektes zu 
  1788.       erhalten. Ein direkter Aufruf eines Destruktors auf einer 
  1789.       Instanzvariablen, die nil enth╨ölt, bricht das Programm mit einem 
  1790.       Laufzeitfehler ab. Die Verwendung von Free verhindert diesen Fehler. 
  1791.  
  1792.      CLASS FUNCTION NewInstance: TObject; VIRTUAL; 
  1793.  
  1794.       Diese Methode wird derzeit nicht verwendet. 
  1795.  
  1796.      PROCEDURE FreeInstance; VIRTUAL; 
  1797.  
  1798.       Diese Methode wird derzeit nicht verwendet. 
  1799.  
  1800.      CLASS FUNCTION InitInstance(Instance: Pointer): TObject; 
  1801.  
  1802.       Die Klassenmethode InitInstance f╨ællt die ╨æbergebene Objektinstanz mit 
  1803.       Nullbytes, wodurch alle ihre Felder zur╨æckgesetzt werden. Die Methode 
  1804.       wird beim Erzeugen eines neuen Objektes vom Konstruktor Create 
  1805.       aufgerufen. 
  1806.  
  1807.      CLASS FUNCTION ClassType: TClass; 
  1808.  
  1809.       Die Klassenmethode ClassType liefert tats╨öchlichen Typ einer Klasse oder 
  1810.       einer Klassenreferenz. Wird die Methode auf einem Objekt aufgerufen, dann 
  1811.       ist dies die tats╨öchliche Klasse des Objekts zur Laufzeit. 
  1812.  
  1813.      CLASS FUNCTION ClassName: STRING; 
  1814.  
  1815.       Die Klassenmethode ClassName liefert den Namen einer Klasse. Wird die 
  1816.       Methode auf einem Objekt aufgerufen, dann ist dies der Name der 
  1817.       tats╨öchlichen Klasse des Objekts zur Laufzeit. 
  1818.  
  1819.       Der Name wird komplett in Gro╤übuchstaben zur╨æckgegeben. 
  1820.  
  1821.      CLASS FUNCTION ClassUnit: STRING; 
  1822.  
  1823.       Die Klassenmethode ClassUnit liefert den Namen des Moduls, in dem eine 
  1824.       Klasse deklariert wurde. 
  1825.  
  1826.      CLASS FUNCTION ClassParent: TClass; 
  1827.  
  1828.       Die Klassenmethode ClassParent liefert den tats╨öchlichen Typ des 
  1829.       unmittelbaren Vorfahren einer Klasse oder einer Klassenreferenz zur╨æck. 
  1830.       Wird die Methode auf einem Objekt aufgerufen, dann ist dies der Vorfahre 
  1831.       der tats╨öchlichen Klasse des Objekts. 
  1832.  
  1833.      CLASS FUNCTION GetClassInfo: POINTER; 
  1834.  
  1835.       Die Klassenmethode GetClassInfo liefert einen Zeiger auf interne 
  1836.       Informationen ╨æber die Klasse. 
  1837.  
  1838.       Achtung: Bei Borland Delphi hei╤üt diese Klassenmethode ClassInfo. Sie 
  1839.       wurde in Speed-Pascal umbenannt, da das OS/2-API bereits eine Funktion 
  1840.       mit dem gleichen Namen bereitstellt. 
  1841.  
  1842.      CLASS FUNCTION InstanceSize: LONGWORD; 
  1843.  
  1844.       Die Klassenmethode InstanceSize liefert die Gr╨ñ╤üe einer Instanz einer 
  1845.       Klasse. 
  1846.  
  1847.      CLASS FUNCTION InheritsFrom(AClass: TClass): BOOLEAN; 
  1848.  
  1849.       Die Klassenmethode InheritsFrom pr╨æft, ob die Klasse, auf der die Methode 
  1850.       aufgerufen wird, ein direkter oder indirekter Nachfahre von AClass ist. 
  1851.       Sie gibt entsprechend True oder False zur╨æck. 
  1852.  
  1853.      PROCEDURE Dispatch(VAR Message); 
  1854.  
  1855.       Die Methode Dispatch dient zum Verteilen von Nachrichten an 
  1856.       botschaftsverarbeitende Methoden. 
  1857.  
  1858.       Dispatch sucht die zur Identifikation der Nachricht passende Methode 
  1859.       heraus und ruft diese auf. 
  1860.  
  1861.       Existiert weder in der tats╨öchlichen Klasse des Objekts noch in einem 
  1862.       beliebigen Vorfahren eine Methode, die die Nachricht behandeln kann, dann 
  1863.       wird die Methode DefaultHandler aufgerufen, die eine Standardbehandlung 
  1864.       der Nachricht durchf╨æhrt. 
  1865.  
  1866.      PROCEDURE DispatchCommand(VAR Message;Command
  1867.  
  1868.       Die Methode DispatchCommand dient zum Verteilen von Nachrichten des Typs 
  1869.       WM_COMMAND an botschaftsverarbeitende Methoden. 
  1870.  
  1871.       DispatchCommand sucht die zur Identifikation der Nachricht passende 
  1872.       Methode heraus und ruft diese auf. 
  1873.  
  1874.       Existiert weder in der tats╨öchlichen Klasse des Objekts noch in einem 
  1875.       beliebigen Vorfahren eine Methode, die die Nachricht behandeln kann, dann 
  1876.       wird die Methode DefaultHandler aufgerufen, die eine Standardbehandlung 
  1877.       der Nachricht durchf╨æhrt. 
  1878.  
  1879.      PROCEDURE FrameDispatch(VAR Message); 
  1880.  
  1881.       Die Methode FrameDispatch dient zum Verteilen von Nachrichten an 
  1882.       botschaftsverarbeitende Methoden. Im Gegensatz zu Dispatch wird 
  1883.       FrameDispatch f╨ær Nachrichten benutzt, die an das Rahmenfenster eines 
  1884.       Bildschirmobjektes gehen sollen. 
  1885.  
  1886.       FrameDispatch f╨ær sucht die zur Identifikation der Nachricht passende 
  1887.       Methode heraus und ruft diese auf. 
  1888.  
  1889.       Existiert weder in der tats╨öchlichen Klasse des Objekts noch in einem 
  1890.       beliebigen Vorfahren eine Methode, die die Nachricht behandeln kann, dann 
  1891.       wird die Methode DefaultFrameHandler aufgerufen, die eine 
  1892.       Standardbehandlung der Nachricht durchf╨æhrt. 
  1893.  
  1894.      PROCEDURE DefaultHandler(VAR Message); VIRTUAL; 
  1895.  
  1896.       Die Methode DefaultHandler wird von Dispatch aufgerufen, wenn keine 
  1897.       Methode zur Behandlung einer bestimmten Botschaft gefunden werden konnte. 
  1898.       DefaultHandler tut nichts, wird aber von graphischen Bildschirmelementen 
  1899.       derart ╨æberschrieben, da╤ü eine Routine des Betriebssystems aufgerufen 
  1900.       wird, die eine Standardbehandlung der Nachricht durchf╨æhrt. 
  1901.  
  1902.      PROCEDURE DefaultFrameHandler(VAR Message); VIRTUAL; 
  1903.  
  1904.       Die Methode DefaultFrameHandler wird von FrameDispatch aufgerufen, wenn 
  1905.       keine Methode zur Behandlung einer bestimmten Botschaft gefunden werden 
  1906.       konnte. DefaultFrameHandler tut nichts, wird aber von graphischen 
  1907.       Bildschirmelementen derart ╨æberschrieben, da╤ü eine Routine des 
  1908.       Betriebssystems aufgerufen wird, die eine Standardbehandlung der 
  1909.       Nachricht durchf╨æhrt. 
  1910.  
  1911.      CLASS FUNCTION MethodAddress(CONST Name: STRING): POINTER; 
  1912.  
  1913.       Die Klassenmethode MethodAddress ermittelt die Einsprungadresse einer 
  1914.       Methode anhand von deren Namen. 
  1915.  
  1916.      CLASS FUNCTION MethodName(Address: POINTER): STRING; 
  1917.  
  1918.       Die Klassenmethode MethodName ermittelt den Namen einer Methode anhand 
  1919.       ihrer Einsprungadresse. 
  1920.  
  1921.      FUNCTION FieldAddress(Name: STRING): POINTER; 
  1922.  
  1923.       Die Methode FieldAddress liefert die Adresse eines Feldes anhand von 
  1924.       dessen Namen. 
  1925.  
  1926.  
  1927. ΓòÉΓòÉΓòÉ 1.10. Exceptions ΓòÉΓòÉΓòÉ
  1928.  
  1929.  ΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûä
  1930.  Exceptions
  1931.  ΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇ
  1932.  
  1933. Was sind Exceptions? 
  1934.  
  1935. Exceptions sind ein Hilfsmittel zur Behandlung von Ausnahmesituationen in 
  1936. Programmen, insbesondere zur Fehlerbehandlung. 
  1937.  
  1938. Wenn eine Exception ausgel╨ñst wird, verzweigt das Programm sofort zu einem 
  1939. Exception-Handler, der auf den Fehler reagieren kann. Existiert kein solcher 
  1940. Exception-Handler dann wird das Programm mit einer Fehlermeldung abgebrochen. 
  1941.  
  1942. Durch die Benutzung von Exceptions wird der normale Kontrollflu╤ü des Programms 
  1943. vom Kontrollflu╤ü f╨ær Fehlerf╨ölle getrennt, wodurch das Programm besser 
  1944. strukturiert und leichter zu warten wird. 
  1945.  
  1946. Exceptions sind Objekte. Neue Exceptions k╨ñnnen von der Vererbung Gebrauch 
  1947. machen, wodurch sich eine baumartige Hierarchie von Exceptions ergibt. Von 
  1948. dieser Struktur profitieren Exception-Handler, indem sie viele spezielle 
  1949. Exceptions, die einen gemeinsamen Vorfahren besitzen, gleichzeitig behandeln. 
  1950.  
  1951. Als Objekte k╨ñnnen Exceptions au╤üerdem beliebige weitere Komponenten besitzen, 
  1952. zum Beispiel Felder f╨ær zus╨ötzliche Informationen, die beim Ausl╨ñsen der 
  1953. Exception gef╨ællt werden. Auch von diesen Informationen kann der 
  1954. Exception-Handler Gebrauch machen, etwa indem eine detaillierte Fehlermeldung 
  1955. angezeigt wird. 
  1956.  
  1957. Deklarieren von Exceptions 
  1958.  
  1959. Die Deklaration einer Exception entspricht der Deklaration einer Klasse, da 
  1960. Exceptions Objekte sind. Exceptions sollten, m╨æssen aber nicht unbedingt von 
  1961. der vordefinierten Klasse Exception oder einer ihrer Nachfahren abstammen. 
  1962.  
  1963. In sehr vielen F╨öllen ist nur die Art des aufgetretenen Fehlers relevant. Diese 
  1964. findet sich dank der zur Laufzeit verf╨ægbaren Typinformationen bereits in der 
  1965. Klasse der Exception wieder. Deshalb werden Exceptions meist sehr einfach 
  1966. deklariert: 
  1967.  
  1968. type
  1969.   EMyException = class(Exception);
  1970.  
  1971. Es ist in Speed-Pascal ╨æblich, die Bezeichner von Exceptions stets mit dem 
  1972. Buchstaben 'E' zu beginnen. 
  1973.  
  1974. Genau wie gew╨ñhnliche Klassen k╨ñnnen auch Exceptions durch geschickte 
  1975. Ausnutzung der Vererbung hierarchisch strukturiert werden. Die vordefinierten 
  1976. Exceptions unterteilen sich zum Beispiel in Prozessorfehler, Speicherfehler, 
  1977. Ein- / Ausgabefehler und mathematische Fehler bei Integer- und 
  1978. Flie╤ükommaoperationen. 
  1979.  
  1980. Dieses System sollten Sie auch bei neuen Exceptions beibehalten, da es 
  1981. ╨æbersichtlicher ist und die Implementierung von Exception-Handlern erleichtert. 
  1982. Wenn Sie eine Reihe von Exceptions f╨ær einen neuen Anwendungsfall oder f╨ær eine 
  1983. neue Klasse deklarieren, dann tun sie dies, indem Sie zuerst eine 
  1984. Basis-Exception einf╨æhren, von der Sie die weiteren ableiten. 
  1985.  
  1986. type
  1987.   ENetworkError  = class(Exception);
  1988.   EWrongUserName = class(ENetworkError);
  1989.   EWrongPassword = class(ENetworkError);
  1990.  
  1991. Es ist m╨ñglich, einer Exception beliebige Komponenten in Form von Feldern, 
  1992. Methoden oder Eigenschaften hinzuzuf╨ægen. Diese Komponenten, meist werden es 
  1993. Felder mit detaillierten Fehlerinformationen sein, k╨ñnnen dann vom 
  1994. Exception-Handler benutzt werden. 
  1995.  
  1996. Die Basisklasse Exception besitzt bereits Felder zur Aufnahme einer 
  1997. Fehlermeldung und einer Fehleradresse. Die Exceptions, die sich mit Ein- / 
  1998. Ausgabefehlern besch╨öftigen, f╨ægen ein Feld mit dem Fehlercode der 
  1999. fehlgeschlagenen Operation hinzu. 
  2000.  
  2001. type
  2002.   EInOutError = class(Exception)
  2003.     ErrorCode: Integer;
  2004.   end;
  2005.  
  2006. Achtung: Im Gegensatz zu Borland Delphi m╨æssen Sie nicht die zus╨ötzliche Unit 
  2007. SysUtils einbinden, um die Fehlerbehandlung ╨æber Exceptions zu aktivieren. 
  2008. S╨ömtliche Fehler des Laufzeitsystems werden bereits ╨æber Exceptions 
  2009. abgewickelt. Der Basistyp Exception ist in der Unit System deklariert. 
  2010.  
  2011. Ausl╨ñsen von Exceptions 
  2012.  
  2013. Eine Exception wird durch das Schl╨æsselwort raise und die Angabe einer 
  2014. Exception-Instanz ausgel╨ñst. Diese Instanz kann und wird meistens genau an 
  2015. dieser Stelle durch einen Konstruktor-Aufruf erzeugt. Es ist aber durchaus 
  2016. m╨ñglich, wenngleich meist ╨æberfl╨æssig, die Instanz vorher zu erzeugen. 
  2017.  
  2018. <Syntaxdiagramm: Raise> 
  2019.  
  2020. Der Konstruktor von Exception erwartet als Parameter einen String. Sie k╨ñnnen 
  2021. darin beim Ausl╨ñsen der Exception eine Fehlermeldung angeben. Sollte das 
  2022. Programm mangels eines passenden Exception-Handlers abgebrochen werden, gibt es 
  2023. zuvor diese Meldung aus. 
  2024.  
  2025.   if Password <> 'top secret' then
  2026.     raise EWrongPassword.Create('Illegal password.');
  2027.  
  2028. Achtung: Im Unterschied zu Borland Delphi ist es derzeit nicht m╨ñglich, eine 
  2029. Fehleradresse mit Hilfe des Schl╨æsselwortes at anzugeben. Als Fehleradresse 
  2030. wird stets die Adresse innerhalb des Codesegmentes angenommen, an der die 
  2031. Exception ausgel╨ñst wurde. 
  2032.  
  2033. Behandeln von Exceptions 
  2034.  
  2035. Wenn Sie nicht wollen, da╤ü Ihr Programm beim Auftreten einer Exception mit 
  2036. einer Fehlermeldung abbricht, dann m╨æssen Sie auf die Exception reagieren. Dazu 
  2037. ╨æberwachen Sie kritische Codesequenzen und f╨ægen ihnen einen Exception-Block 
  2038. hinzu. Der Exception-Block enth╨ölt Code, der nur im Fehlerfall ausgef╨æhrt 
  2039. werden soll. Er kann einen einen oder mehrere Exception-Handler bereitstellen, 
  2040. die Fehler innerhalb der ╨æberwachten Codesequenz behandeln. 
  2041.  
  2042. Wenn innerhalb des ╨æberwachten Abschnitts eine Exception ausgel╨ñst wird, tritt 
  2043. sofort der Exception-Block in Aktion. 
  2044.  
  2045. Wird der ╨æberwachte Abschnitt fehlerfrei beendet, wird die Ausf╨æhrung hinter 
  2046. dem Exception-Block wiederaufgenommen. 
  2047.  
  2048. Bei verschachtelten ╨æberwachten Codesequenzen genie╤üt stets der Exception-Block 
  2049. die h╨ñchste Priorit╨öt, der zur innersten ╨æberwachten Sequenz geh╨ñrt. Behandelt 
  2050. er eine aufgetretene Exception nicht, wird sie nach au╤üen durchgereicht. 
  2051.  
  2052. ╨¬berwachte Codesequenzen und Exception-Handler 
  2053.  
  2054. <Syntaxdiagramm: Try_Except> 
  2055.  
  2056. Eine Anweisungsfolge, die von den Schl╨æsselw╨ñrtern try..except eingeschlossen 
  2057. wird, ist eine ╨æberwachte Codesequenz. 
  2058.  
  2059. Wenn innerhalb dieser Codesequenz eine Exception ausgel╨ñst wird, dann verzweigt 
  2060. das Programm unmittelbar zu der Anweisungsfolge, die sich zwischen den 
  2061. Schl╨æsselw╨ñrtern except..end befindet und als Exception-Block bezeichnet wird. 
  2062.  
  2063. Dieser Exception-Block kann einen oder mehrere Exception-Handler bereitstellen, 
  2064. um bestimmte Fehler zu behandeln. Er kann auch einen universellen 
  2065. Exception-Handler beinhalten, der jede Art von Fehler behandelt. 
  2066.  
  2067. try
  2068.   /*Die folgenden Anweisungen sind kritisch. Wenn die Datei
  2069.     nicht ge╨ñffnet werden kann, oder sich w╨öhrend des Lesens
  2070.     Probleme einstellen, dann wird eine Exception ausgel╨ñst.
  2071.     Das Programm verzweigt dann unmittelbar zum EXCEPT..END-
  2072.     Block, der den Fehler behandeln solle. */
  2073.  
  2074.   Assign(F, 'c:\userdata\report.txt');
  2075.   Reset(F);
  2076.   ...
  2077.   Close(F);
  2078.  
  2079. except
  2080.   ...
  2081. end;
  2082.  
  2083. Der Exception-Block kann auf die Fehlerbedingung reagieren, mu╤ü dies aber nicht 
  2084. tun. Ob ein Exception-Block auf eine bestimmte Art von Exception reagiert, kann 
  2085. vom Programmierer festgelegt werden. Im allgemeinsten Fall werden die 
  2086. Exceptions nicht weiter differenziert. Es ergibt sich ein universeller 
  2087. Exception-Handler, der jede Art von Exception behandelt. 
  2088.  
  2089. except
  2090.   /*Dies ist ein universeller Exception-Handler. Der Code
  2091.     zwischen EXCEPT..END wird in jedem Fehlerfall ausgef╨æhrt.
  2092.     Der Fehler wird dadurch beseitigt. */
  2093.  
  2094.   WriteLn('Unbekannter Fehler beim Lesen der Datei.');
  2095. end;
  2096.  
  2097. Durch Einsatz der Schl╨æsselw╨ñrter on..do kann die Arbeit des Exception-Blockes 
  2098. auf eine oder mehrere Arten von Exceptions eingeschr╨önkt werden. Jedes on..do 
  2099. definiert einen Handler f╨ær eine bestimmte Klasse von Exceptions. 
  2100.  
  2101. except
  2102.   /*Dieser Exception-Handler bearbeitet nur Fehler vom Typ
  2103.     'EFileNotFound'. Alle weiteren Exceptions reicht er an die
  2104.     n╨öchsth╨ñhere Ebene weiter. */
  2105.  
  2106.   on EFileNotFound do
  2107.     WriteLn('Die angegebene Datei existiert nicht.');
  2108. end;
  2109.  
  2110. Es k╨ñnnen mit on..do beliebig viele Exception-Handler angegeben werden. Das 
  2111. Laufzeitsystem geht sie im Fehlerfall der Reihe nach durch. Sobald ein 
  2112. passender Exception-Handler gefunden wird, wird dessen Code ausgef╨æhrt, und der 
  2113. Fehler wird beseitigt. Es wird niemals mehr als ein Exception-Handler 
  2114. ausgef╨æhrt. 
  2115.  
  2116. Beachten Sie, da╤ü ein Exception-Handler auch immer alle Nachfahren der Klasse 
  2117. behandelt, f╨ær die er installiert wurde. Deshalb sollten speziellere 
  2118. Exception-Handler in der Liste stets weiter vorn stehen, da sie sonst niemals 
  2119. erreicht werden. 
  2120.  
  2121. Ausgehend davon, da╤ü alle Exceptions, die im Zusammenhang mit Dateioperationen 
  2122. stehen, einen gemeinsamen Vorfahren EInOutError besitzen, k╨ñnnte eine 
  2123. Fehlerbehandlung etwa wie folgt aussehen: 
  2124.  
  2125. except
  2126.   /*Diese Exception-Handler bearbeiten eine Reihe von Fehlern.
  2127.     Die spezielleren Handler stehen dabei weiter vorn, die
  2128.     allgemeineren am Ende der Liste. */
  2129.  
  2130.   on EFileNotFound do
  2131.     WriteLn('Die angegebene Datei existiert nicht.');
  2132.  
  2133.   on EAccessDenied do
  2134.     WriteLn('Zugriff auf die Datei verweigert.');
  2135.  
  2136.   on EInvalidFilename do
  2137.     WriteLn('Ung╨æltiger Dateiname.');
  2138.  
  2139.   on EInOutError do
  2140.     WriteLn('Ein-/Ausgabefehler beim Lesen der Datei.');
  2141. end;
  2142.  
  2143. Bei Angabe einer Liste von Exception-Handlern mit on..do ist es au╤üerdem 
  2144. m╨ñglich, im Anschlu╤ü an den letzten Exception-Handler mit else einen weiteren 
  2145. anzugeben, der alle Exceptions behandelt, auf die nicht bereits einer der 
  2146. speziellen Handler reagiert hat. 
  2147.  
  2148. except
  2149.   /*Diese Exception-Handler bearbeiten eine Reihe von Fehlern.
  2150.     Die spezielleren Handler stehen dabei weiter vorn, die
  2151.     allgemeineren am Ende der Liste. Fehler, die nicht mit der
  2152.     Ein-/Ausgabeoperation in Zusammenhang stehen, werden durch
  2153.     den ELSE-Teil behandelt. */
  2154.  
  2155.   on EFileNotFound do
  2156.     WriteLn('Die angegebene Datei existiert nicht.');
  2157.   on EAccessDenied do
  2158.     WriteLn('Zugriff auf die Datei verweigert.');
  2159.   on EInvalidFilename do
  2160.     WriteLn('Ung╨æltiger Dateiname.');
  2161.  
  2162.   on EInOutError do
  2163.     WriteLn('Ein-/Ausgabefehler beim Lesen der Datei.');
  2164.  
  2165.   else
  2166.     WriteLn('Unbekannter Fehler beim Lesen der Datei.');
  2167. end;
  2168.  
  2169. Wird eine Exception innerhalb des Exception-Blocks behandelt, dann wird sie 
  2170. beseitigt, und die Ausf╨æhrung wird unmittelbar hinter dem except..end-Block 
  2171. wiederaufgenommen. Behandelt keiner der Exception-Handler den aufgetretenen 
  2172. Fehler, dann bleibt die Exception bestehen. Der eingebaute Exception-Handler 
  2173. von Speed-Pascal tritt in Aktion und beendet das Programm mit einer 
  2174. Fehlermeldung, es sei denn, der gesamte Abschnitt befindet sich innerhalb einer 
  2175. weiteren mittels try..except ╨æberwachten Codesequenz. 
  2176.  
  2177. Tritt innerhalb der ╨æberwachten Codesequenz gar keine Exception auf, dann 
  2178. verzweigt das Programm nach Beendigung des try..except-Blockes unmittelbar 
  2179. hinter das Ende des Exception-Blockes. Es besteht in diesem Fall keine 
  2180. Veranlassung, die Fehlerbehandlung aufzurufen. 
  2181.  
  2182. Beachten Sie, da╤ü es sich bei der Verzweigung im Fehlerfall um einen 
  2183. unmittelbaren Sprung handelt, nicht um einen Prozeduraufruf. Der Stack wird 
  2184. soweit aufger╨öumt, da╤ü er sich im gleichen Zustand befindet wie beim Betreten 
  2185. der ╨æberwachten Codesequenz. Danach wird die Exception-Behandlung angesprungen. 
  2186. Nach der Behandlung der Exception kann kein R╨æcksprung an die Fehleradresse 
  2187. mehr stattfinden. Stattdessen wird die Ausf╨æhrung hinter dem except..end-Block 
  2188. wiederaufgenommen. 
  2189.  
  2190. Geschachtelte Exception-Handler 
  2191.  
  2192. Es ist m╨ñglich, ╨æberwachte Codesequenzen zu schachteln. Dies kann entweder 
  2193. direkt durch Schachtelung von try..except-Anweisungen geschehen oder indirekt 
  2194. dadurch, da╤ü innerhalb der ╨æberwachten Codesequenz aufgerufene Prozeduren oder 
  2195. Funktionen selbst lokal Codesequenzen ╨æberwachen. In beiden F╨öllen werden die 
  2196. zugeh╨ñrigen except..end-Bl╨ñcke auf eine Art Stapel gelegt, wobei sich der zum 
  2197. zuletzt betretenen try..except-Block geh╨ñrende zuoberst befindet. 
  2198.  
  2199. Tritt eine Exception auf, so wird zum obersten auf dem Stapel befindlichen 
  2200. except..end-Block verzweigt. Dieser geh╨ñrt zu genau der ╨æberwachten 
  2201. Codesequenz, die zuletzt betreten und noch nicht wieder beendet wurde. Falls 
  2202. hier ein Exception-Handler existiert, der die aufgetretene Exception behandelt, 
  2203. findet die Behandlung statt, und die Exception wird gel╨ñscht. Die Ausf╨æhrung 
  2204. wird hinter dem except..end-Block wiederaufgenommen. 
  2205.  
  2206. Behandelt keiner der Exception-Handler die aufgetretene Exception, so wird der 
  2207. except..end-Block vom Stapel abger╨öumt, und es wird zum n╨öchsten 
  2208. except..end-Block verzeigt. Dies geschieht solange, bis ein Exception-Handler 
  2209. den aufgetretenen Fehler behandelt. Existiert kein solcher Exception-Handler, 
  2210. tritt die eingebaute Fehlerbehandlung von Speed-Pascal in Aktion. Das Programm 
  2211. wird abgebrochen. 
  2212.  
  2213. Ausl╨ñsen von Exceptions im Exception-Handler 
  2214.  
  2215. Bei Schachtelung von ╨æberwachten Codesequenzen kann es sinnvoll sein, lokal auf 
  2216. den Fehler zu reagieren, aber die Fehlerbedingung bestehen zu lassen, damit die 
  2217. n╨öchsth╨ñhere Ebene auch darauf reagieren kann. In diesem Fall kann innerhalb 
  2218. des except..end-Blockes durch Einsatz von raise ohne jeden weiteren Parameter 
  2219. daf╨ær gesorgt werden, da╤ü die aufgetretene Exception unmittelbar wieder 
  2220. ausgel╨ñst wird. Der except..end-Block wird vom Stapel abger╨öumt, und es wird so 
  2221. verfahren, als w╨öre die Exception nicht behandelt worden. Diese spezielle 
  2222. syntaktische Variante von raise kann nur innerhalb eines Exception-Handlers 
  2223. benutzt werden. 
  2224.  
  2225. Es ist auch m╨ñglich, mittels der normalen Syntax von raise eine andere 
  2226. Exception innerhalb eines except..end-Blockes auszul╨ñsen. Wird diese Exception 
  2227. nicht lokal innerhalb des except..end-Blockes behandelt, dann verdr╨öngt sie die 
  2228. urspr╨ængliche Exception. Diese wird gel╨ñscht, der except..end-Block wird vom 
  2229. Stapel abger╨öumt, und die Behandlung der neuen Exception wird an die 
  2230. n╨öchsth╨ñhere Ebene verwiesen. 
  2231.  
  2232. Dies kann manchmal sinnvoll sein, wenn mehrere lokal auftretende Exceptions 
  2233. abgefangen und in einen gemeinsamen Typ von Exception umgewandelt werden 
  2234. sollen, der von der n╨öchsth╨ñheren Ebene behandelt wird. 
  2235.  
  2236. Es kann aber auch zu unerw╨ænschten Ergebnissen f╨æhren, wenn nicht beachtet 
  2237. wird, da╤ü innerhalb eines - m╨ñglicherweise sehr komplexen - Exception-Handlers 
  2238. wiederum Fehler auftreten k╨ñnnen. In diesem Fall sollten Sie den kritischen 
  2239. Bereich innerhalb des Exception-Handlers wiederum in einen try..except-Block 
  2240. mit anschlie╤üendem except..end-Block einschlie╤üen. Exceptions, die innerhalb 
  2241. des inneren Exception-Handlers nicht bearbeitet werden, verdr╨öngen die 
  2242. Exception des ╨öu╤üeren Handlers und werden an die n╨öchsth╨ñhere Ebene verwiesen. 
  2243.  
  2244. Zugriff auf die Exception-Instanz 
  2245.  
  2246. Es ist m╨ñglich, innerhalb eines Exception-Handlers auf die Exception-Instanz 
  2247. zuzugreifen. Das ist sinnvoll, wenn die aufgetretene Exception zus╨ötzliche 
  2248. Informationen enth╨ölt, die vom Handler ausgewertet werden sollen. 
  2249.  
  2250. Zum Zugriff auf die Exception-Instanz kann einem durch on..do eingeleiteten 
  2251. Exception-Handler ein Bezeichner gefolgt von einem Doppelpunkt vorangestellt 
  2252. werden. Innerhalb dieses einen Exception-Handlers steht dann unter dem 
  2253. angegebenen Bezeichner die Instanz der aufgetretenen Exception zur Verf╨ægung. 
  2254. Der Typ des Bezeichners entspricht der Exception-Klasse, die der Handler 
  2255. bearbeitet, ist also eine passende Objektreferenz. 
  2256.  
  2257. Das folgende Beispiel soll die M╨ñglichkeiten verdeutlichen. Die 
  2258. Exception-Klasse EInOutError und deren Nachfahren besitzen ein Feld ErrorCode, 
  2259. das den Fehlercode des aufgetretenen Fehlers enth╨ölt. Diesen Fehlercode k╨ñnnte 
  2260. sich ein Exception-Handler zunutze machen. 
  2261.  
  2262. try
  2263.   Assign(F, 'c:\userdata\report.txt');
  2264.   Reset(F);
  2265.   ...
  2266.   Close(F);
  2267.  
  2268. except
  2269.   on E: EInOutError do
  2270.     WriteLn('Ein-/Ausgabefehler ', E.ErrorCode, ' beim Lesen der Datei.');
  2271.   else
  2272.     WriteLn('Unbekannter Fehler beim Lesen der Datei.');
  2273. end;
  2274.  
  2275. Beachten Sie, da╤ü es nicht n╨ñtig ist, die Variable mittels var zu deklarieren. 
  2276. Der Bezeichner wird an der entsprechenden Stelle generiert und ist nur 
  2277. innerhalb des zugeh╨ñrigen Exception-Handlers g╨æltig. 
  2278.  
  2279. Achtung: Sie haben ╨æber den Bezeichner auch Zugriff auf alle Methoden der 
  2280. Instanz. Gehen Sie sehr vorsichtig mit dieser M╨ñglichkeit um. Versuchen Sie 
  2281. insbesondere niemals, die Exception-Instanz mittels Destroy oder Free selbst zu 
  2282. l╨ñschen. Das ist Aufgabe des Exception-Handlers. Der Versuch, dies 'von Hand' 
  2283. zu erledigen, w╨ærde das Laufzeitsystem derart durcheinander bringen, da╤ü das 
  2284. Programm mit hoher Wahrscheinlichkeit abst╨ærzt. 
  2285.  
  2286. Sch╨ætzen von Resourcen 
  2287.  
  2288. Wenn innerhalb einer fehleranf╨ölligen Codesequenz Resourcen belegt werden, dann 
  2289. ist es notwendig, diese auch beim Auftreten einer Exception wieder freigeben zu 
  2290. k╨ñnnen. Anderenfalls gehen die Resourcen m╨ñglicherweise dauerhaft verloren, da 
  2291. das Auftreten der Exception einen direkten Sprung zum Exception-Handler zufolge 
  2292. hat. Die Anweisungen, die die Benutzung der Resource abschlie╤üen und diese 
  2293. freigeben, werden im Fehlerfall gar nicht erreicht. 
  2294.  
  2295. Die try..finally-Anweisung dient dazu, die Freigabe von Resourcen auch im 
  2296. Fehlerfall zu garantieren. 
  2297.  
  2298. <Syntaxdiagramm: Try_Finally> 
  2299.  
  2300. Um zu garantieren, da╤ü eine bestimmte Codesequenz auch beim Auftreten einer 
  2301. Exception ausgef╨æhrt wird, gehen Sie wie folgt vor: 
  2302.  
  2303.      Setzen Sie die Anweisungen, die die Resource allokieren, vor den 
  2304.       try..finally-Block. 
  2305.  
  2306.      Schlie╤üen Sie die Arbeit mit der Resource in den try..finally-Block ein. 
  2307.  
  2308.      Schlie╤üen Sie die Anweisungen zum Freigeben der Resource in den 
  2309.       finally..end-Block ein. 
  2310.  
  2311.   /*Zuerst wird die Resource allokiert. In diesem Fall wird
  2312.     versucht, eine Datei zu ╨ñffnen. */
  2313.  
  2314.   Assign(F, 'c:\userdata\report.txt');
  2315.   Reset(F);
  2316.  
  2317.   try
  2318.     // Lesen der Datei. M╨ñglicherweise treten hier Fehler auf.
  2319.     ...
  2320.   finally
  2321.     // Die Datei soll in jedem Fall geschlossen werden.
  2322.  
  2323.     Close(F);
  2324.   end;
  2325.  
  2326.  Wird innerhalb des try..finally-Blocks eines Exception ausgel╨ñst, verzweigt 
  2327.  das Programm zuerst zum finally..end-Block. Wenn dieser beendet ist, wird die 
  2328.  Exception an den zust╨öndigen Exception-Handler weitergereicht, falls ein 
  2329.  solcher existiert. 
  2330.  
  2331.  Beachten Sie, da╤ü die Exception innerhalb eines finally..end-Abschnittes nicht 
  2332.  behandelt wird. Dieser Bereich ist kein Exception-Handler, er garantiert nur 
  2333.  die Ausf╨æhrung einer Reihe von Anweisungen unabh╨öngig davon, ob ein Fehler 
  2334.  auftritt oder nicht. Um auf den Fehler zu reagieren, mu╤ü der gesamte Abschnitt 
  2335.  gesch╨ætzt und mit einem Exception-Handler versehen werden. Es ist nicht 
  2336.  m╨ñglich, finally und except zu kombinieren, etwa derart, da╤ü der except-Block 
  2337.  auf den finally-Block folgt. 
  2338.  
  2339.   try
  2340.  
  2341.     /*Zuerst wird die Resource allokiert. In diesem Fall wird
  2342.       versucht, eine Datei zu ╨ñffnen. */
  2343.  
  2344.     Assign(F, 'c:\userdata\report.txt');
  2345.     Reset(F);
  2346.  
  2347.     try
  2348.       // Lesen der Datei. M╨ñglicherweise treten hier Fehler auf.
  2349.       ...
  2350.     finally
  2351.       // Die Datei soll in jedem Fall geschlossen werden.
  2352.  
  2353.       Close(F);
  2354.     end;
  2355.  
  2356.   except
  2357.     WriteLn('Es trat ein Fehler beim Lesen der Datei auf.');
  2358.   end;
  2359.  
  2360.  Es ist m╨ñglich, try..finally-Bl╨ñcke ineinander zu schachteln. Es ist dann auf 
  2361.  jeder Ebene sichergestellt, da╤ü die Anweisungen zwischen finally..end 
  2362.  ausgef╨æhrt werden, bevor zur n╨öchsth╨ñheren Ebene verzweigt wird. 
  2363.  
  2364.  Achtung: Falls innerhalb eines finally..end-Blockes eine Exception ausgel╨ñst 
  2365.  wird, die dort nicht lokal behandelt wird, verdr╨öngt sie die urspr╨ængliche 
  2366.  Exception und verzeigt zum n╨öchsten zust╨öndigen Exception-Handler. Das 
  2367.  Verhalten ist zwar definiert, aber es ist nicht empfehlenswert, da╤ü Sie davon 
  2368.  Gebrauch machen. Stellen Sie stattdessen sicher, da╤ü Exceptions, die in 
  2369.  finally..end-Bl╨ñcken auftreten, auch dort behandelt werden. 
  2370.  
  2371.  Exceptions und Objekte 
  2372.  
  2373.  Exceptions k╨ñnnen ohne Einschr╨önkung innerhalb von Objektmethoden verwendet 
  2374.  werden. Es gibt jedoch eine Besonderheit zu beachten. Wenn innerhalb eines 
  2375.  Konstruktor-Aufrufes eine Exception auftritt, die dort nicht behandelt wird, 
  2376.  dann wird zuerst der Destruktor aufgerufen, bevor zum m╨ñglicherweise 
  2377.  vorhandenen Exception-Handler verzweigt wird. 
  2378.  
  2379.  Damit verhalten sich Konstruktoren exakt so, als w╨ören sie auf die folgende 
  2380.  Weise implementiert: 
  2381.  
  2382.   constructor TMyClass.Create;
  2383.   begin
  2384.     try
  2385.       // Gew╨ænschte Anweisungen zwischen BEGIN und END
  2386.     except
  2387.       Destroy;
  2388.       raise;
  2389.     end;
  2390.   end;
  2391.  
  2392.  Aufgrund dieses Verhaltens ist es wichtig, da╤ü ein Destruktor auch mit nicht 
  2393.  vollst╨öndig initialisierten Objekten umzugehen wei╤ü, denn er kann theoretisch 
  2394.  von jeder beliebigen Stelle des Konstruktors aus aufgerufen werden. 
  2395.  
  2396.  
  2397. ΓòÉΓòÉΓòÉ 1.11. Vordefinierte Exceptions ΓòÉΓòÉΓòÉ
  2398.  
  2399.  ΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûäΓûä
  2400.  Vordefinierte Exceptions
  2401.  ΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇΓûÇ
  2402.  
  2403. Basisklasse Exception 
  2404.  
  2405. S╨ömtliche Laufzeitfehler von Speed-Pascal werden ╨æber Exceptions abgewickelt. 
  2406. Dazu sind in der Unit System bereits eine Reihe von Exceptions vordefiniert. 
  2407.  
  2408. Exception = class(TObject)
  2409. public
  2410.   constructor Create(const Msg: String);
  2411.   destructor Destroy; override;
  2412.  
  2413.   property Message: string;     // lesen / schreiben
  2414.   property MessagePtr: PString; // nur lesen
  2415. end;
  2416.  
  2417. ExceptClass = class of Exception.
  2418.  
  2419. Exception ist die Basisklasse f╨ær Ausnahmebedingungen. Von ihr sollten alle 
  2420. weiteren Exception-Klassen abgeleitet werden. Exception selbst wird selten 
  2421. ausgel╨ñst, meist werden es spezialisierte Nachkommen sein, die auf bestimmte 
  2422. Fehler hinweisen. Alle Exception-Klassen erben von Exception Konstruktor, 
  2423. Destruktor sowie die Eigenschaft Message, die die Fehlermeldung enth╨ölt, die 
  2424. beim Ausl╨ñsen der Exception an den Konstruktor ╨æbergeben wird. 
  2425.  
  2426. Software-generierte Exceptions 
  2427.  
  2428.      EProcessTerm = class(Exception); 
  2429.  
  2430.       EProcessTerm wird vom Betriebssystem ausgel╨ñst, wenn der Proze╤ü beendet 
  2431.       werden soll. 
  2432.  
  2433.  Hardware-generierte Exceptions 
  2434.  
  2435.      EProcessorException = class(Exception); 
  2436.  
  2437.       EProcessorException ist der Vorfahr f╨ær weitere vom Prozessor ausgel╨ñste 
  2438.       Exceptions. Es wird niemals EProcessorException selbst ausgel╨ñst, sondern 
  2439.       stets ein Nachkomme, der auf eine bestimmte Ausnahmebedingung hinweist. 
  2440.  
  2441.       Im Unterschied zu EFault weist EProcessorException nicht unbedingt auf 
  2442.       einen Fehler hin, denn die Nachfahren EBreakpint und ESingleStep dienen 
  2443.       zum Debuggen eines Programms. 
  2444.  
  2445.      EFault = class(EProcessorException); 
  2446.  
  2447.       EFault ist der Vorfahr f╨ær alle vom Prozessor ausgel╨ñsten Exceptions, die 
  2448.       auf einen Fehler hinweisen. Es wird niemals EFault ausgel╨ñst, sondern 
  2449.       stets ein Nachkomme, der auf eine bestimmte Fehlerbedingung hinweist. 
  2450.  
  2451.       Im Gegensatz zu EProcessorException weist EFault immer auf einen Fehler 
  2452.       hin. 
  2453.  
  2454.      EGPFault = class(EFault); 
  2455.  
  2456.       EGPFault wird ausgel╨ñst, wenn eine allgemeine Schutzverletzung auftritt. 
  2457.       Eine Schutzverletzung liegt vor, wenn ein Proze╤ü auf Speicherbereiche 
  2458.       zugreift, die nicht innerhalb seines Adre╤üraums liegen. 
  2459.  
  2460.       Meist deutet dieser Fehler darauf hin, da╤ü eine illegale Zeigeroperation 
  2461.       durchgef╨æhrt wurde oder da╤ü mit einem nicht korrekt initialisierten 
  2462.       Objekt gearbeitet wurde. 
  2463.  
  2464.      EStackFault = class(EFault); 
  2465.  
  2466.       EStackFault wird ausgel╨ñst, wenn nicht gen╨ægend Stackspeicher vorhanden 
  2467.       ist, um die aktuelle Operation durchzuf╨æhren. Prozeduren und Funktionen 
  2468.       reservieren beim Aufruf den Speicher f╨ær ihre lokalen Variablen auf dem 
  2469.       Stack. 
  2470.  
  2471.       Wenn dieser Fehler auftritt, dann teilen Sie dem Programm mehr 
  2472.       Stackspeicher zu oder vermeiden Sie die Benutzung zu vieler lokaler 
  2473.       Variablen, insbesondere bei Rekursion. 
  2474.  
  2475.       Diese Exception kann nur auftreten, wenn die Stackpr╨æfung aktiviert ist, 
  2476.       die Operation also im Modus $S+ compiliert wird. 
  2477.  
  2478.      EPageFault = class(EFault); 
  2479.  
  2480.       EPageFault wird vom Prozessor ausgel╨ñst, wenn ein Seitenfehler auftritt. 
  2481.       Ein Seitenfehler liegt vor, wenn der Proze╤ü auf eine Speicherseite 
  2482.       zugreifen will, die momentan ausgelagert ist. 
  2483.  
  2484.       Dieser Fehler sollte normalerweise nicht auftreten, da sich das 
  2485.       Betriebssystem um die Verwaltung des physikalischen und virtuellen 
  2486.       Speichers k╨æmmert und die entsprechende Seite automatisch wieder 
  2487.       einlagert. 
  2488.  
  2489.      EInvalidOpCode = class(EFault); 
  2490.  
  2491.       EInvalidOpCode wird vom Prozessor ausgel╨ñst, wenn dieser auf eine 
  2492.       illegale Maschineninstruktion trifft. 
  2493.  
  2494.      EBreakpoint = class(EProcessorException); 
  2495.  
  2496.       EBreakpoint wird vom Prozessor ausgel╨ñst, wenn dieser auf einen 
  2497.       Breakpoint trifft. 
  2498.  
  2499.      ESingleStep = class(EProcessorException); 
  2500.  
  2501.       ESingleStep wird vom Prozessor nach jedem durchgef╨æhrten Befehl 
  2502.       ausgel╨ñst, wenn das Programm im Einzelschrittmodus abgearbeitet wird. 
  2503.  
  2504.  Exceptions bei Speicher-Operationen 
  2505.  
  2506.      EOutOfMemory = class(Exception); 
  2507.  
  2508.       EOutOfMemory wird ausgel╨ñst, wenn eine angeforderte Menge Speicher nicht 
  2509.       mehr auf dem Heap zur Verf╨ægung steht. 
  2510.  
  2511.      EInvalidPointer = class(Exception); 
  2512.  
  2513.       EInvalidPointer wird ausgel╨ñst, wenn ein Programm versucht, einen 
  2514.       Speicherbereich zu deallokieren, der nicht zuvor allokiert wurde oder 
  2515.       bereits freigegeben ist. 
  2516.  
  2517.      EInvalidHeap = class(Exception); 
  2518.  
  2519.       EInvalidHeap wird ausgel╨ñst, wenn der Heapbereich der Applikation 
  2520.       besch╨ödigt ist. Dies kann vorkommen, wenn die Applikation durch 
  2521.       fehlerhafte Zeigeroperationen Speicherbereiche ╨æberschreibt, die f╨ær die 
  2522.       Heapverwaltung wichtig sind. 
  2523.  
  2524.  Exceptions bei Ein- / Ausgabeoperationen 
  2525.  
  2526.     
  2527.  
  2528.             EInOutError = class(Exception)
  2529.             public
  2530.               ErrorCode: Integer;
  2531.             end;
  2532.  
  2533.       EInOutError ist der Vorfahr f╨ær eine Reihe von Exceptions, die auf Ein- / 
  2534.       Ausgabe-Fehler hinweisen. Alle Exceptions dieser Art besitzen ein 
  2535.       zus╨ötzliches Feld, das den Fehlercode aufnehmen kann, der bei der 
  2536.       Operation aufgetreten ist. 
  2537.  
  2538.       Damit diese Exception und ihre Nachfahren auftreten k╨ñnnen, mu╤ü die Ein- 
  2539.       / Ausgabe-╨¬berpr╨æfung aktiviert sein, die entsprechende Operation mu╤ü 
  2540.       also im Modus $I+ compiliert werden. 
  2541.  
  2542.      EAccessDenied = class(EInOutError); 
  2543.  
  2544.       EAccessDenied wird ausgel╨ñst, wenn das ╨⌐ffnen einer Datei fehlschl╨ögt, 
  2545.       weil entweder die Attribute der Datei ein ╨⌐ffnen zum Schreiben nicht 
  2546.       erlauben, oder weil die Datei bereits von einem anderen Proze╤ü exklusiv 
  2547.       ge╨ñffnet wurde. 
  2548.  
  2549.      EDiskFull = class(EInOutError); 
  2550.  
  2551.       EDiskFull wird ausgel╨ñst, wenn die Diskette oder Festplatte, auf die der 
  2552.       Proze╤ü schreiben will, voll ist. 
  2553.  
  2554.      EEndOfFile = class(EInOutError); 
  2555.  
  2556.       EEndOfFile wird ausgel╨ñst, wenn der Proze╤ü versucht, ╨æber das Ende einer 
  2557.       Datei hinaus zu lesen. 
  2558.  
  2559.      EFileNotFound = class(EInOutError); 
  2560.  
  2561.       EFileNotFound wird ausgel╨ñst, wenn der Proze╤ü versucht, eine Datei zu 
  2562.       ╨ñffnen, die nicht existiert. 
  2563.  
  2564.      EInvalidFileName = class(EInOutError); 
  2565.  
  2566.       EInvalidFileName wird ausgel╨ñst, wenn ein illegaler Dateiname benutzt 
  2567.       wird, der zum Beispiel zu lang ist oder Sonderzeichen enth╨ölt, die nicht 
  2568.       Teil  eines Dateinamens sein d╨ærfen. 
  2569.  
  2570.      EInvalidInput = class(EInOutError); 
  2571.  
  2572.       EInvalidInput wird ausgel╨ñst, wenn der Benutzer des Programms eine 
  2573.       ung╨æltige Eingabe macht. 
  2574.  
  2575.      ETooManyOpenFiles = class(EInOutError); 
  2576.  
  2577.       ETooManyOpenFiles wird ausgel╨ñst, wenn zu viele Dateien gleichzeitig 
  2578.       ge╨ñffnet sind. Wenn der Fehler auftritt, erh╨ñhen Sie die entsprechende 
  2579.       Einstellung des Betriebssystems, um mehr gleichzeitig ge╨ñffnete Dateien 
  2580.       zu erlauben. 
  2581.  
  2582.  Mathematische Exceptions bei Integer-Operationen 
  2583.  
  2584.      EIntError = class(Exception); 
  2585.  
  2586.       EIntError ist der gemeinsame Vorfahr einer Reihe von Exceptions, die auf 
  2587.       Fehler bei mathematischen Operationen mit Integer-Werten hinweisen. 
  2588.  
  2589.      EDivByZero = class(EIntError); 
  2590.  
  2591.       EDivByZero wird ausgel╨ñst, wenn eine Division durch Null versucht wird. 
  2592.  
  2593.      ERangeError = class(EIntError); 
  2594.  
  2595.       ERangeError wird ausgel╨ñst, wenn f╨ær das Ergebnis einer mathematischen 
  2596.       Operation eine Bereichspr╨æfung fehlschl╨ögt. Damit diese Exception 
  2597.       auftreten kann, mu╤ü die Operation im Modus $R+ compiliert werden. 
  2598.  
  2599.      EIntOverflow = class(EIntError); 
  2600.  
  2601.       EIntOverflow wird ausgel╨ñst, wenn das Ergebnis einer mathematischen 
  2602.       Operation einen ╨¬berlauf produziert hat. Damit dieser Fehler auftreten 
  2603.       kann, mu╤ü die Operation im Modus $Q+ compiliert werden. 
  2604.  
  2605.  Mathematische Exceptions bei Flie╤ükomma-Operationen 
  2606.  
  2607.      EMathError = class(Exception); 
  2608.  
  2609.       EIntError ist der gemeinsame Vorfahr einer Reihe von Exceptions, die auf 
  2610.       Fehler bei mathematischen Operationen mit Integer-Werten hinweisen. 
  2611.  
  2612.      EInvalidOp = class(EMathError); 
  2613.  
  2614.       EInvalidOp wird ausgel╨ñst, wenn eine ung╨æltige mathematisch Operation 
  2615.       versucht wird, z.B. das Ziehen der Wurzel aus einer negativen Zahl. 
  2616.  
  2617.      EZeroDivide = class(EMathError); 
  2618.  
  2619.       EZeroDivide wird ausgel╨ñst, wenn eine Division durch Null versucht wird. 
  2620.  
  2621.      EOverflow = class(EMathError); 
  2622.  
  2623.       EOverflow wird ausgel╨ñst, wenn das Ergebnis einer mathematischen 
  2624.       Operation einen ╨¬berlauf produziert hat. 
  2625.  
  2626.      EUnderflow = class(EMathError); 
  2627.  
  2628.       EUnderflow wird ausgel╨ñst, wenn das Ergebnis einer mathematischen 
  2629.       Operation so klein ist, da╤ü es mit der Pr╨özision der Ergebnisvariablen 
  2630.       nicht mehr dargestellt werden kann. 
  2631.  
  2632.       Dieser Fehler tritt normalerweise nicht auf. Stattdessen liefert 
  2633.       Speed-Pascal den Wert Null als Ergebnis zur╨æck. Durch ╨₧ndern des 
  2634.       Kontrollwortes des mathematischen Koprozessors kann das Ausl╨ñsen dieser 
  2635.       Exception jedoch erm╨ñglicht werden. 
  2636.  
  2637.  Exceptions bei Typwandlungen 
  2638.  
  2639.      EInvalidCast = class(Exception); 
  2640.  
  2641.       EInvalidCast wird ausgel╨ñst, wenn eine Typwandlung mit Hilfe des 
  2642.       Operators as fehlschl╨ögt. 
  2643.  
  2644.      EConvertError = class(Exception); 
  2645.  
  2646.       EConvertError wird bei einer Reihe von Konvertierungsfunktionen 
  2647.       ausgel╨ñst, wenn der Quellwert ung╨æltig ist.