4D v16.3Projektmethoden |
|||||||||||||||||||||||
|
4D v16.3
Projektmethoden
|
Parametertyp | Übergeben als | Kommentar |
Feld, Variable oder Ausdruck eines skalaren Typs (Zahl, Text, Datum...) | Wert | Lässt sich durch einen Zeiger als Referenz übergeben, siehe unten |
Feld, Variable oder Ausdruck vom Typ Objekt | Referenz | Siehe Beispiel unten |
Variable oder Ausdruck vom Typ Collection | Referenz | |
Variable oder Ausdruck vom Typ Zeiger | Referenz | Siehe Zeiger in Methoden |
Array | Lässt sich nicht direkt als Parameter übergeben | Lässt sich durch einen Zeiger als Referenz übergeben, siehe Arrays und Zeiger |
Tabelle | Lässt sich nicht direkt als Parameter übergeben | Lässt sich durch einen Zeiger als Referenz übergeben, siehe Zeiger |
Bei Feldern, Variablen und Ausdrücken vom skalaren Typ werden als Parameter für Methoden nur Kopien der Werte übergeben.
Da $1, $2 lokale Variablen sind, sind sie nur innerhalb der Unterroutine verfügbar und werden am Ende der Unterroutine gelöscht. Von daher kann eine Unterroutine nicht den Wert der aktuellen Datenfelder oder Variablen ändern, die auf Methodenebene als Parameter übergeben werden. Beispiel:
` Ausschnitt aus dem Code der Methode MY METHOD
` ...
DO SOMETHING([People]Last Name) ` [People]Last Name sei gleich "weber"
ALERT([People]Last Name)
` Code der Methode DO SOMETHING
$1:=Uppercase($1)
ALERT($1)
Die von DO SOMETHING angezeigte Meldung liest “WEBER”, die von MY METHOD angezeigte Meldung liest “weber”. Die Methode hat den Wert des Parameters $1 lokal geändert, das verändert jedoch nicht den Wert des Datenfeldes [People]Last Name, der von der Methode MY METHOD als Parameter übergeben wurde.
Es gibt zwei Möglichkeiten, den Wert des Datenfeldes in der Methode DO SOMETHING zu ändern:
1. Sie übergeben in der Methode nicht das Datenfeld, sondern einen Zeiger darauf:
` Ausschnitt aus dem Code der Methode MY METHOD
` ...
DO SOMETHING(->[People]Last Name) ` [People]Last Name sei gleich "weber"
ALERT([People]Last Name)
` Code der Methode DO SOMETHING
$1->:=Uppercase($1->)
ALERT($1->)
Der Parameter ist hier nicht das Datenfeld selbst, sondern ein Zeiger darauf. Das von $1 referenzierte Objekt ($1->) ist das aktuelle Datenfeld. Wird nun das referenzierte Objekt geändert, geht das über die Reichweite der Unterroutine hinaus und wirkt sich auf das aktuelle Datenfeld aus. In diesem Beispiel lesen beide Meldedialoge “WEBER”.
Weitere Informationen dazu finden Sie im Abschnitt WA GET EXTERNAL LINKS FILTERS.
2. Sie können die Methode DO SOMETHING so umschreiben, dass sie nicht etwas ausführt, sondern einen Wert zurückgibt:
` Ausschnitt aus dem Code der Methode MY METHOD
` ...
[People]Last Name:=DO SOMETHING([People]Last Name)
` [People]Last Name sei gleich "weber"
ALERT([People]Last Name)
` Code der Methode DO SOMETHING
$0:=Uppercase($1)
ALERT($0)
Diese Technik heißt auch “eine Funktion verwenden”. Sie wird im nächsten Abschnitt beschrieben.
Bei Verwendung von Variablen, Ausdrücken oder Feldern vom Typ Objekt oder Collection als Parameter von Methoden werden Referenzen auf aktuelle Ausgangswerte übergeben. In diesem Fall enthält $1, $2... keine Werte sondern Referenzen. Wird der Wert von $1, $2... in der Unterroutine geändert, wirkt sich die Änderung überall aus, wo das Quellobjekt oder die Collection verwendet werden. Das ist das gleiche Prinzip wie für Zeiger, mit dem Unterschied, dass die Parameter $1, $2... in der Unterroutine nicht dereferenziert werden müssen.
Zum Beispiel:
//Die Methode CreatePerson erstellt ein Objekt und sendet es als Parameter
C_OBJECT($person)
$person:=New object("Name";"Smith";"Age";40)
ChangeAge($person)
ALERT(String(OB get($person;"Age")))
//Die Methode ChangeAge fügt 10 zum Attribut Age des empfangenen Objekts hinzu
C_OBJECT($1)
OB SET($1;"Age";OB Get($1;"Age")+10)
ALERT(String(OB get($1;"Age")))
Bei Ausführen der Methode CreatePerson lesen beide Meldungsboxen "50", da beide Methoden dieselbe Referenz verwalten.
4D Server: Werden Parameter zwischen Methoden übergeben, die nicht auf demselben Rechner ausgeführt werden (z.B. die Option Execute on Server, siehe Eigenschaften für Projektmethoden), lassen sich Referenzen nicht verwenden. In diesen Fällen werden anstelle von Referenzen Kopien von Objekt und Collection Parametern gesendet.
Daten können auch von Methoden zurückgeben werden. Eine Methode, die einen Wert zurückgibt, heißt Funktion.
4D oder 4D Plug-in Befehle, die einen Wert zurückgeben, heißen ebenfalls Funktionen.
Folgende Programmierzeile verwendet die vordefinierte Funktion Length, sie gibt die Länge einer Zeichenkette zurück. Der von Length zurückgegebene Wert wird in eine Variable mit Namen MyLength gesetzt:
MyLength:=Length("How did I get here?")
Jede Unterroutine kann einen Wert zurückgeben. Der zurückzugebende Wert wird in die lokale Variable $0 gesetzt.
Folgende Funktion mit Namen Uppercase4 gibt eine Zeichenkette mit den ersten vier Zeichen in Großbuchstaben zurück:
$0:=Uppercase(Substring($1;1;4))+Substring($1;5)
Dieses Beispiel verwendet die Funktion Uppercase4:
NewPhrase:=Uppercase4("This is good.")
Die Variable NewPhrase erhält “THIS is good.”
Das Ergebnis der Funktion $0 ist eine lokale Variable in der Unterroutine. Sie kann als solche in der Unterroutine verwendet werden. Im vorigen Beispiel DO SOMETHING wurde $0 zuerst der Wert von $1 zugewiesen, dann war sie Parameter für den Befehl ALERT. Sie können $0 in der Unterroutine genauso wie jede andere lokale Variable verwenden. 4D übergibt der aufgerufenen Methode den Wert von $0 (so als ob die Unterroutine endet).
Projektmethoden können sich auch selbst aufrufen, d.h. sie sind rekursiv. Beispiel:
Die 4D Programmiersprache unterstützt Rekursivität.
Hier ein Beispiel. Wir haben eine Tabelle [Friends and Relatives], die extrem vereinfacht, so aussieht:
- [Friends and Relatives]Name
- [Friends and Relatives]Children'Name
Wir gehen davon aus, dass die Werte der Datenfelder einmalig sind, d.h. es gibt nicht zwei Personen mit demselben Namen. Sie wollen für einen gegebenen Namen folgenden Satz erstellen: “Hans, mein Freund, der das Kind ist von Paul, der das Kind ist von Susi, die das Kind ist von Robert, der das Kind ist von Elisabeth, tut dies für sein Leben gern!”:
1. Sie können den Satz folgendermaßen anlegen:
$vsName:=Request("Gib den Namen ein:";"Hans")
If(OK=1)
QUERY([Friends and Relatives];[Friends and Relatives]Name=$vsName)
If(Records in selection([Friends and Relatives])>0)
$vtTheWholeStory:="Mein Freund, "+$vsName
Repeat
QUERY([Friends and Relatives];[Friends and Relatives]Children'Name=$vsName)
$vlQueryResult:=Records in selection([Friends and Relatives])
If($vlQueryResult>0)
$vtTheWholeStory:=$vtTheWholeStory+" der das Kind ist von
"+[Friends and Relatives]Name
$vsName:=[Friends and Relatives]Name
End if
Until($vlQueryResult=0)
$vtTheWholeStory:=$vtTheWholeStory+", tut dies für sein Leben gern!"
ALERT($vtTheWholeStory)
End if
End if
2. oder folgendermaßen:
$vsName:=Request("Gib den Namen ein:";"Hans")
If(OK=1)
QUERY([Friends and Relatives];[Friends and Relatives]Name=$vsName)
If(Records in selection([Friends and Relatives])>0)
ALERT("Mein Freund, "+Genealogy of($vsName)+", tut dies für sein Leben gern!")
End if
End if
mit der rekursiven Methode Genealogy of:
` Projektmethode Genealogy of
` Genealogy of ( String ) -> Text
` Genealogy of ( Name ) -> Satzteil
$0:=$1
QUERY([Friends and Relatives];[Friends and Relatives]Children'Name=$1)
If(Records in selection([Friends and Relatives])>0)
$0:=$0+" der das Kind ist von "+Genealogy of([Friends and Relatives]Name)
End if
Beachten Sie die Methode Genealogy of, die sich selbst aufruft.
Die erste Möglichkeit ist ein iterativer Algorithmus, die zweite ein rekursiver Algorithmus.
Hinweis: Sie können bei Programmierungen wie im oben aufgeführten Beispiel sowohl iterative als auch rekursive Methoden schreiben. Rekursivität macht die Programmierung im allgemeinen präziser, leichter zu lesen und zu warten, sie ist jedoch nicht zwingend.
Einige typische Verwendungen für Rekursivität in 4D sind:
Wichtig: Rekursive Abfragen sollten immer an einem bestimmten Punkt enden. Im Beispiel ruft sich die Methode Genealogy of nicht mehr selbst auf, wenn die Suche keinen Datensatz zurückgibt. Ohne Abfragen dieser Bedingung würde sich die Methode endlos aufrufen; 4D gibt dann evtl. eine Fehlermeldung “Speicher voll” zurück, da es keinen Platze mehr hat zum Stapeln der Aufrufe (so wie bei Parametern und lokalen Variablen in den Methoden).
Produkt: 4D
Thema: Grundbegriffe
4D Programmiersprache ( 4D v16)
4D Programmiersprache ( 4D v16.1)
4D Programmiersprache ( 4D v16.2)
4D Programmiersprache ( 4D v16.3)