Dieses Dokument beschreibt, wie eine Anwendung durch Definition und Benutzung von Klassen entwickelt wird.
Es umfasst die folgenden Themen:
Klassen auf Windows-Plattformen entwickeln
Auf Windows-Plattformen stellt Natural den Class Builder als Werkzeug zur Entwicklung
von Natural-Klassen zur Verfügung. Der Class Builder präsentiert eine Natural-Klasse
in einer strukturierten hierarchischen Reihenfolge und ermöglicht es dem Benutzer, die
Klassen und ihre Komponenten effizient zu verwalten. Wenn Sie den Class Builder
benutzen, sind überhaupt keine Vorkenntnisse oder auch nur Grundkenntnisse der unten
beschriebenen Syntax-Elemente erforderlich.
Klassen mit SPoD entwickeln
In einer Natural Single Point of Development-Umgebung (SPoD), der zentralen Umgebung
für Entwicklungen einschließlich eines Großrechners und/oder UNIX Remote Development
Servers (DFÜ-Entwicklungsserver) können Sie den Class Builder benutzen, der zusammen
mit der Natural Studio-Benutzeroberfläche zur Entwicklung von Klassen auf Großrechnern
und/oder UNIX-Plattformen zur Verfügung steht. In diesem Fall sind keine Vorkenntnisse
oder auch nur Grundkenntnisse der im Folgenden beschriebenen Syntax-Elemente
erforderlich.
Klassen auf Großrechner- oder UNIX-Plattformen entwickeln
Wenn Sie SpoD nicht benutzen, entwickeln Sie mittels des Natural-Programm-Editors
Klassen auf diesen Plattformen. In diesem Fall sollten Sie die Syntax der unten
beschriebenen Klassen-Definition kennen.
Wenn Sie eine Klasse definieren, müssen Sie ein Natural-Klassenmodul definieren,
innerhalb dessen Sie ein DEFINE
CLASS-Statement erstellen. Mittels des DEFINE
CLASS-Statements können Sie der Klasse einen extern verwendbaren Namen zuweisen und
ihre Schnittstellen, Methoden und Eigenschaften definieren. Der Klasse kann auch ein
Objekt-Datenbereich zugewiesen werden, der das Layout einer Instanz der Klasse beschreibt.
Dieser Abschnitt umfasst die folgenden Themen:
Um ein Natural-Klassenmodul zu erstellen
Benutzen Sie das CREATE
OBJECT-Statement zur Erstellung eines Natural-Objekts des Typs
Klasse.
Das DEFINE CLASS-Statement
definiert den Namen der Klasse, die Schnittstellen, die die Klasse unterstützt, und die
Struktur ihrer Objekte.
Um eine Klasse zu spezifizieren
Benutzen Sie das DEFINE
CLASS-Statement, das in der
Statements-Dokumentation beschrieben ist.
Jede Schnittstelle einer Klasse wird mit einem INTERFACE-Statement innerhalb der Klassen-Definition
angegeben. Ein INTERFACE-Statement gibt den Namen der Schnittstelle und
eine Anzahl von Eigenschaften und Methoden an. Für Klassen, die als COM-Klassen
registriert werden sollen, gibt es auch die Globally Unique ID der Schnittstelle an.
Eine Klasse kann eine oder mehrere Schnittstellen haben. Für jede Schnittstelle wird
ein INTERFACE-Statement in der Klassen-Definition kodiert. Jedes
INTERFACE-Statement enthält eine oder mehrere PROPERTY- und
METHOD-Klauseln. Gewöhnlich stehen die in einer Schnittstelle
enthaltenen Eigenschaften und Methoden miteinander in einem technischen oder
betriebswirtschaftlichen Zusammenhang.
Die PROPERTY-Klausel definiert den Namen einer Eigenschaft und
weist der Eigenschaft eine Variable vom Objekt-Datenbereich zu. Diese Variable wird zum
Speichern des Wertes der Eigenschaft benutzt.
Die METHOD-Klausel definiert den Namen einer Methode und weist
der Methode ein Subprogramm zu. Dieses Subprogramm wird zum Implementieren der Methode
benutzt.
Um eine Schnittstelle zu definieren
Benutzen Sie das INTERFACE-Statement (siehe
Statements-Dokumentation).
Das PROPERTY-Statement wird
nur benutzt, wenn mehrere Klassen dieselbe Schnittstelle auf verschiedene Art und Weise
implementieren sollen. In diesem Fall benutzen die Klassen dieselbe
Schnittstellen-Definition gemeinsam und beziehen sie von einem Natural-Copycode ein. Das
PROPERTY-Statement wird dann benutzt, um außerhalb der
Schnittstellen-Definition eine Variable vom Objekt-Datenbereich einer Eigenschaft
zuzuweisen. Wie die PROPERTY-Klausel des INTERFACE-Statements definiert das
PROPERTY-Statement den Namen einer Eigenschaft und weist eine Variable vom
Objekt-Datenbereich der Eigenschaft zu. Diese Variable wird zum Speichern des Wertes der
Eigenschaft benutzt.
Um eine Objekt-Datenvariable einer Eigenschaft zuzuweisen
Benutzen Sie das PROPERTY-Statement (siehe
Statements-Dokumentation).
Das METHOD-Statement wird nur
benutzt, wenn mehrere Klassen dieselbe Schnittstelle auf verschiedene Arten
implementieren sollen. In diesem Fall benutzen die Klassen dieselbe
Schnittstellen-Definition gemeinsam und beziehen sie von einem Natural-Copycode ein. Das METHOD-Statement
wird dann benutzt, um außerhalb der Schnittstellen-Definition der Methode ein
Subprogramm zuzuweisen. Wie die METHOD-Klausel des INTERFACE-Statements definiert das
METHOD-Statement den Namen einer Methode und weist der Methode ein
Subprogramm zu. Dieses Subprogramm wird zum Implementieren der Methode benutzt.
Um einer Methode ein Subprogramm zuzuweisen
Benutzen Sie das METHOD-Statement (siehe
Statements-Dokumentation).
Eine Methode wird in der folgenden allgemeinen Form als ein Natural-Subprogramm implementiert:
DEFINE DATA * * Implementation code of the method * END
Informationen zum DEFINE
DATA-Statement siehe
Statements-Dokumentation.
Alle Klauseln des DEFINE DATA-Statements sind optional.
Um die Daten-Konsistenz sicherzustellen, empfiehlt es sich, dass Sie keine Inline-Datendefinitionen, sondern Data Areas benutzen.
Wenn eine PARAMETER-Klausel angegeben wird, kann die Methode Parameter
und/oder einen Rückgabewert haben.
Mit BY VALUE in
der Parameter Data Area markierte Parameter sind Eingabe-Parameter der Methode.
Nicht mit BY VALUE markierte Parameter werden "By Reference"
übergeben und sind Eingabe/Ausgabe-Parameter. Dies ist die Voreinstellung.
Der erste mit BY VALUE
RESULT markierte Parameter wird als Rückgabewert für die Methode
zurückgegeben. Wenn mehr als ein Parameter auf diese Art markiert wird, werden die
anderen als Eingabe/Ausgabe-Parameter behandelt.
Als OPTIONAL
markierte Parameter brauchen nicht angegeben zu werden, wenn die Methode aufgerufen wird
und Sie die nX-Notation im SEND METHOD-Statement benutzen.
Um sicherzustellen, dass das Methoden-Subprogramm genau dieselben Parameter akzeptiert,
wie in dem entsprechenden METHOD-Statement in der Klassen-Definition angegeben,
benutzen Sie eine Parameter Data Area anstatt von Inline-Datendefinitionen. Benutzen Sie
dieselbe Parameter Data Area wie in dem betreffenden METHOD-Statement.
Um dem Methoden-Subprogramm Zugriff auf die Objektdaten-Struktur zu geben, kann die
OBJECT-Klausel
angegeben werden. Um sicherzustellen, dass das Methoden-Subprogramm korrekt auf die
Objektdaten zugreifen kann, benutzen Sie eine Local Data Area anstatt von
Inline-Datendefinitionen. Verwenden Sie dieselbe Local Data Area, wie in der OBJECT-Klausel des
DEFINE CLASS-Statements
angegeben.
Die Klauseln GLOBAL,
LOCAL und INDEPENDENT können wie in jedem
anderen Natural-Programm benutzt werden.
Obwohl es technisch möglich ist, macht es gewöhnlich keinen Sinn, eine CONTEXT-Klausel in einem
Methoden-Subprogramm zu benutzen.
In dem folgenden Beispiel werden Daten über eine vorgegebene Person von einer Tabelle
eingelesen. Der Suchschlüssel wird als ein BY VALUE-Parameter
übergeben. Die sich daraus ergebenden Daten werden über “by reference”-Parameter
zurückgegeben ("By Reference" ist die Standard-Definition). Der
Rückgabewert der Methode wird durch die Spezifikation BY VALUE RESULT
definiert.

Auf in einer lokalen Natural-Session erstellte Objekte kann von anderen Modulen aus in derselben Natural-Session zugegriffen werden.
Das Statement CREATE OBJECT wird
benutzt, um ein Objekt (auch als Instance bezeichnet) einer gegebenen Klasse zu
erstellen.
Um Objekte in Natural-Programmen zu referenzieren, müssen Object-Handles im DEFINE DATA-Statement definiert werden.
Methoden eines Objekts werden mit dem Statement SEND METHOD aufgerufen. Objekte können Eigenschaften haben,
auf die mit der normalen Zuweisungssyntax zugegriffen wird.
Diese Schritte sind im Folgenden beschrieben:
Um Objekte in Natural-Programmen zu referenzieren, müssen Object-Handles im
DEFINE DATA-Statement wie folgt definiert werden:
DEFINE DATA
|
level-handle-name
[(array-definition)] HANDLE OF
OBJECT
|
| ... |
END-DEFINE
|
Beispiel:
DEFINE DATA LOCAL 1 #MYOBJ1 HANDLE OF OBJECT 1 #MYOBJ2 (1:5) HANDLE OF OBJECT END-DEFINE
Um eine Instanz einer Klasse zu erstellen
Benutzen Sie das CREATE
OBJECT-Statement (siehe Natural
Statements-Dokumentation).
Um eine bestimmte Methode eines Objekts aufzurufen
Benutzen Sie das SEND
METHOD-Statement (siehe Natural
Statements-Dokumentation).
Auf Properties kann mit dem Statement ASSIGN (oder COMPUTE) wie folgt zugegriffen werden:
ASSIGN
operand1.property-name =
operand2
|
ASSIGN
operand2 =
operand1.property-name
|
Operand1 muss als eine Object-Handle definiert werden und identifiziert das Objekt, dessen Eigenschaft aufgerufen werden soll. Das Objekt muss bereits vorhanden sein.
Als operand2 geben Sie einen Operanden an, dessen Format datenübertragungskompatibel zu dem Format der Eigenschaft sein muss. Weitere Informationen siehe Kompatibilitätsregeln zur Datenübertragung.
Der Name einer Property des Objekts.
Stimmt der Name der Property mit der Natural Identifier Syntax überein, kann er wie folgt angegeben werden:
create object #o1 of class "Employee" #age := #o1.Age
Wenn der Name der Property nicht mit der Natural Identifier Syntax übereinstimmt, muss er in spitze Klammern gesetzt werden:
create object #o1 of class "Employee" #salary := #o1.<<%Salary>>
Der Name der Property kann auch mit einem Schnittstellen-Namen qualifiziert werden. Dies ist erforderlich, wenn das Objekt mehr als eine Schnittstelle hat, die eine Property mit demselben Namen enthält. In diesem Fall muss der qualifizierte Name der Property in spitzen Klammern stehen:
create object #o1 of class "Employee" #age := #o1.<<PersonalData.Age>>
Beispiel:
define data local 1 #i (i2) 1 #o handle of object 1 #p (5) handle of object 1 #q (5) handle of object 1 #salary (p7.2) 1 #history (p7.2/1:10) end-define * ... * Code omitted for brevity. * ... * Set/Read the Salary property of the object #o. #o.Salary := #salary #salary := #o.Salary * Set/Read the Salary property of * the second object of the array #p. #p.Salary(2) := #salary #salary := #p.Salary(2) * * Set/Read the SalaryHistory property of the object #o. #o.SalaryHistory := #history(1:10) #history(1:10) := #o.SalaryHistory * Set/Read the SalaryHistory property of * the second object of the array #p. #p.SalaryHistory(2) := #history(1:10) #history(1:10) := #p.SalaryHistory(2) * * Set the Salary property of each object in #p to the same value. #p.Salary(*) := #salary * Set the SalaryHistory property of each object in #p * to the same value. #p.SalaryHistory(*) := #history(1:10) * * Set the Salary property of each object in #p to the value * of the Salary property of the corresponding object in #q. #p.Salary(*) := #q.Salary(*) * Set the SalaryHistory property of each object in #p to the value * of the SalaryHistory property of the corresponding object in #q. #p.SalaryHistory(*) := #q.SalaryHistory(*) * end
Um Arrays von Objekt-Handles und Eigenschaften mit Arrays als Werte korrekt benutzen zu können, ist es wichtig, Folgendes zu wissen:
Eine Eigenschaft einer Array-Ausprägung von Objekt-Handles wird mit der folgenden Index-Notation adressiert:
#p.Salary(2) := #salary
Auf eine Eigenschaft, die ein Array als Wert hat, wird stets als Ganzes zugegriffen. Deshalb ist keine Index-Notation mit dem Namen der Eigenschaft erforderlich:
#o.SalaryHistory := #history(1:10)
Eine Eigenschaft einer Array-Ausprägung von Objekt-Handles, die ein Array als Wert hat, wird deswegen wie folgt adressiert:
#p.SalaryHistory(2) := #history(1:10)