PRIVATE Variable
Definition einer PRIVATE Variablen
PRIVATE Variablen werden dynamisch erzeugt und "entsorgt".
Eine PRIVATE Variable kann auf drei verschiedenen Wegen erzeugt werden:
- durch die (ausführbare!) Anweisung "PRIVATE cVar" - durch eine Wertzuweisung "cVar := 'Heute'" - durch die Anweisung PARAMETER in einer Funktion (die übergebenen Werte werden in die vorgegebenen Variablen übernommen)
In den beiden ersten Fällen wird eine Variable mit dem Namen cVar erzeugt.
FUNCTION TueIrgendEtwas LOCAL nI PRIVATE dHeute PARAMETER nEins, nZwei, lVier cZeit := Time()
Innerhalb dieser Funktion sind damit fünf PRIVATE Variable definiert: - dHeute - nEins - nZwei - lVier - cZeit (vorausgesetzt, es existiert keine PUBLIC oder STATIC Variable dieses Namens)
Unterschiede zu lexikalischen Variablen
PRIVATE Variablen können "on the fly" definiert und zerstört werden. Es muss keine Deklaration wie in anderen Sprachen durchgeführt werden. Dies ist sehr bequem und bringt die Gefahr mit sich, dass PRIVATE Variablen sich "überlagern" und damit ungewünschte Effekte erzeugen.
FUNCTION Main PRIVATE nIndex FOR nIndex := 1 TO 3 ? ProcName() + " " + Str(nIndex, 2) TueWas(nIndex) NEXT WAIT RETURN(.T.) FUNCTION TueWas(nWert) FOR nIndex := 1 TO 5 ? ProcName() + " " + Str(nWert * nIndex, 3) NEXT RETURN(.T.)
Bei Aufruf dieses Programms wird folgendes am Bildschirm ausgegeben:
MAIN 1 TUEWAS 1 TUEWAS 2 TUEWAS 3 TUEWAS 4 TUEWAS 5
In TueWas() wird nIndex angesprochen. Gäbe es diese Variable nicht (in unserem Beispiel wurde sie in Main() erzeugt), würde sie durch die Zuweisung in der FOR-Anweisung erzeugt. Da sie aber existiert, wird die existierende Variable verwendet. Nach dem Durchlauf der Schleife in TueWas() hat die Variable nIndex den Wert 6 und daher wird die Schleife in Main() beendet.
Um diesen Effekt zu vermeiden, muss die Funktion TueWas() leicht erweitert werden:
FUNCTION TueWas(nWert) PRIVATE nIndex FOR nIndex := 1 TO 5 ? ProcName() + " " + Str(nWert * nIndex, 3) NEXT RETURN(.T.)
Dadurch, dass eine explizite Deklaration aufgenommen wurde, wird in TueWas() eine separate PRIVATE Variable nIndex erzeugt, die nicht mehr mit der in Main() definierten identisch ist.
Dieses Beispiel zeigt, dass die bequeme Anlage von PRIVATE Variablen durch Wertzuweisung auch ihre Schattenseiten hat, wenn es bereits eine PRIVATE Variable dieses Namens gibt.
Besonderheiten
Eine PRIVATE Variable ist an ihre Position im Call-Stack gebunden. (Sichtbar ist sie, wie das vorige Beispiel zeigt in der Funktion, in der sie deklariert wird, sowie in allen daraus aufgerufenen Funktionen bis zu dem Zeitpunkt, da die Funktion, in der sie deklariert wurde, endet.)
FUNCTION Main() ProcA() ProcB() RETURN(.T.) FUNCTION ProcA() ProcC() ... RETURN(.T.) FUNCTION ProcB() ProcC() ... RETURN(.T.) FUNCTION ProcC() cVar := "Hugo" RETURN(.T.)
cVar wird das erste Mal in folgender Aufruf-Konstellation (= Call-Stack) angesprochen:
Main() +---> ProcA() +---> ProcC()
cVar wird in ProcC() erzeugt und ist in dem Moment, in dem ProcC durch die RETURN-Anweisung verlassen wird, nicht mehr "adressierbar".
Wenn später über ProcB() ein weiterer Aufruf von ProcC() erfolgt, wird eine neue (!) PRIVATE Variable erzeugt:
Main +---> ProcB() +---> ProcC()
Auch für diese Variable endet ihre Lebenszeit, wenn ProcC mit RETURN verlassen wird.
Sichtbarkeit von LOCAL Variablen
Genaueres findet sich hier: Lebenszeit und Sichtbarkeit der Variablen-Klassen