Variabili e Proprieta'
Come e Perche' 

 Dan Howard 

Traduzione di Antonio Campagna - Marzo 2001

Introduzione 

In Visual dBASE una causa molto frequente di confusione è l'uso delle proprietà al posto delle variabili. In questo articolo tenterò di chiarire il fare e non fare uso di variabili. 
Per lo scopo di questo articolo, quando uso il termine funzione, mi riferisco sia ad una procedura, sia ad una funzione, sia ad un metodo. Quando uso il termine proprietà generalmente mi riferisco ad una proprietà custom. 
Anche se la maggior parte del codice di esempio è stato scritto per Visual dBASE 7.01, basteranno piccole modifiche per garantire la compatibilità con la versione 5.7. 

Che cosa sono le Variabili? 

Dalla guida in linea di Visual dBASE: 
Le variabili sono locazioni di memoria con nome, in cui vengono memorizzati valori corrispondenti ai dati: stringhe, numeri, valori logici, date, valori null, riferimenti a oggetti, puntatori di funzione e blocchi di codice. Si può assegnare a ciascuno di questi valori un nome in modo che in seguito sia possibile rintracciarli o modificarli. È possibile usare questi valori per registrare quanto viene immesso dall'utente, per eseguire calcoli, per effettuare confronti, per definire valori utilizzati come parametri per altre istruzioni, e per molte altre cose. 

In aggiunta a quanto detto: le variabili sono dichiarate e usate nelle procedure, nelle funzioni e nei metodi. Gli oggetti non usano variabili lo fanno solamente i loro metodi. 

In verità gli oggetti potrebbero usare le variabili, ma sarebbe meglio che si evitasse tale situazione. Spero che alla fine di questo articolo si comprenderà il perché. 

Tipi di Variabili 

Ci sono 4 tipi base di variabili: pubbliche o globali (public), private, statiche (static) e locali (local). Ciascun tipo ha la propria visibilità (o campo di azione) e durata. 

Visibilità: per visibilità di una variabile si fa riferimento alla parte del programma in cui è visibile tale variabile. Le variabili possono essere visibili all'intera applicazione o solamente nella funzione nella quale sono state dichiarate. * 
Durata: per durata di una variabile si intende per quanto tempo la variabile conterrà il valore in essa memorizzato. Le variabili possono essere "vive" per tutta l'applicazione o solamente nella funzione nella quale sono state dichiarate. 

[* nota: L'eccezione è la variabile di tipo Private che è anche disponibile in qualsiasi sottoroutine di livello più basso. Vedremo su questo un esempio nella sezione "Gotcha".] 

La seguente tabella mostra i diversi tipi variabili con la loro visibilità e durata. Includo anche se con tali variabili puoi (o non puoi) usare l'operatore macro (&) (Vedi Macro nella guida in linea per maggiori informazioni): 

 Tipo  Visibilità  Durata  Macro
 public Disponibile per l'intera applicazione fino alla fine dell'applicazione  SI
 private Disponibile solo nella funzione dove è stata dichiarata e in ogni sotto routine di livello inferiore  fino alla fine della funzione   SI
 static Disponibile solo nella funzione dove è stata dichiarata fino alla fine dell'applicazione  No
 local Disponibile solo nella funzione dove è stata dichiarata fino alla fine della funzione  No


Dichiarazioni di Variabili 

Di solito è una buona regola di programmazione dichiarare prima dell'uso qualsiasi variabile. Diversamente per default la variabile sarà di tipo "private", il che non sempre è quello che vogliamo. Questo è come normalmente dichiaro la mie variabili: 

local a,b,c 
store 0 to a,b,c

La ragione per cui faccio così è legata all'operatore := che è stato introdotto con Visual dBASE 7. := è unicamente un operatore di assegnamento. Una volta che la tua variabile è stata dichiarata ed le è stato assegnato un valore, puoi usare l'operatore := esclusivamente per prevenire la creazione fortuita di una nuova variabile. Questo vale anche per le proprietà. 
Fai attenzione che non interessa quello che inizialmente memorizzi nella variabile. Purché tu metta qualcosa (anche Null) nella variabile, puoi usare l'operatore :=

C'è da notare che dBASE diversamente da molti linguaggi, ti permette di dichiarare le variabili dovunque all'interno delle tue funzioni. Per esempio, il seguente codice è perfettamente valido: 

Function MyVariables 
    local j //
dichiarazione all'inizio del corpo della funzione 
    for j = 1 to 10 
        ?j 
    next j 
    private c //
dichiarazione all'interno del corpo della funzione 
    c = "dan" 
    ?c 
return 

Sebbene dBASE permette quanto su visto, generalmente dovresti dichiarare le tue variabili all'inizio della funzione ciò faciliterà le operazioni di debug delle tue applicazioni. 

Usando Varabili 

Di seguito esamineremo alcuni esempi di ciascun tipo di variabile ed il relativo uso: 

Variabili Locali (local) 

Le variabili locali sono probabilmente il tipo più frequente che userai. Le variabili locali possono essere usate per qualsiasi scopo eccetto l'uso con l'operatore macro (&) e la funzione type(). 
N.B. maggiori informazione nella GIL (Guida In Linea) 

Function MyFunction.. 
    local j 
    store 0 to j 
    private k 
    store 0 to k 
    ?type("j") //
restituirà sempre "U" 
    ?type("k") //
restituirà "N" 
return 

Variabili Private

Generalmente riservo le variabili private per quei casi dove ho bisogno di usare l'operatore macro (&) o la funzione type(). Ovviamente si tratta del mio stile di programmazione. Tu puoi usare certamente le variabili private in qualsiasi altra circostanza anche al posto delle variabili locali, ma dovresti essere consapevole che le variabili di tipo privato, possono essere modificate in tutte le sottoroutine di livello inferiore. Dal mio punto di vista, modificare il valore di una variabile in una funzione dove non è stata dichiarata, è cattiva programmazione perché potrebbe creare maggiori difficoltà nelle operazioni di debug. Ecco di seguito un esempio sull'uso delle variabili private: 

Function Pushbutton1_onClick 
    private o,m_macro 

    m_macro = "form.entryfield1" 
    o = &m_macro. //
operatore macro 
    if type("o.dataLink") = "O" 
     ?"Il datalink per questo controllo é un oggetto campo" 
    endif 
return 

N.B. puoi evitare l'uso delle variabili private per la funzione type() usando invece questa piccola funzione: 

// Chiama questa funzione come la funzione type() 
//eccetto per il fatto che non si usano le virgolette. ad es. 

 if LocalType(o.dataLink) = "O" // nota la mancanza delle virgolette 
     ?"Il datalink per questo controllo é un oggetto campo" 
 endif 

Function LocalType 
    param xValue 
return type('xValue') 


Tramite la funzione precedente si restringe l'uso delle variabili private per le macro. 

Variabili Statiche (static) 

Fra i tipi di variabili le statiche sono probabilmente le meno comuni. Esse sono un ibrido tra le variabili pubbliche e quelle locali. Come le locali si possono usare solamente nella funzione nella quale sono state dichiarate, ma esse sono anche simili alle variabili pubbliche in quanto conservano i valori memorizzati finché non chiudi dBASE(o invii un CLEAR MEMORY). Guarda nella guida in linea l'esempio mostrato con la funzione stopwatch per farti un'idea sull'uso delle variabili statiche (immetti help static nella finestra comandi). Le variabili statiche sono interessanti in quanto sono le uniche variabili che possono essere assegnate in "linea". Ciò significa che possono essere dichiarate ed assegnate contemporaneamente.

// Incremento un contatore ogni volta che effettuo una chiamata. 
Function HitCounter 
    static n = 0
// Questa linea sarà eseguita solamente la prima volta che la funzione è chiamata. 
    n++
// oppure n = n + 1 per dBASE 5.x 
return ( n ) 

L'utilità delle variabili statiche risiede nel fatto che sono solamente accessibili dalla loro funzione. Questa caratteristica ti permette di usarle per quelle variabili dove vuoi assicurati che siano inizializzate correttamente. 

// Function INIFilename 
// Restiusce il file INI correntemente in uso o modifica  
// le impostazioni solamente se il file (INI) già esiste

Function INIFileName( cFile ) 
    static cIniFile = '' 

    / / Se mi fosse passato un parametro 
    if argcount() = 1 
        if not file( cFile ) 
            msgbox('Non posso modificare ' + cFile + ', perchè non esiste!') 
        else 
            cIniFile := cFile 
        endif 
    endif 
return ( cIniFile ) 

Le variabili statiche in un ambiente come dBASE potrebbero essere poco utili, in quanto la "funzionalità" stessa può essere disponibile attraverso le tecniche di OOP. Quindi non ti biasimerò se non ne farai uso. ;-) 

Variabili Pubbliche (Public) 

Le variabili pubbliche sono variabili globali. Puoi riferirti ad esse da qualsiasi routine della tua applicazione. Esse sono dichiarate come nell'esempio: 

public a 
a = 10 

Le variabili pubbliche appaiono essere tra i tipi di variabili più controverse. Nel newsgroups c'è stato un ampio dibattito se farne uso o meno. Le variabili pubbliche sono utili per avere specifiche informazioni circa l'applicazione ed es.:

  • un riferimento all'oggetto Ini;

  • Informazioni sulla versione;

  • Informazioni sull'utente;

  • Impostazioni sulla lingua.

Tuttavia uno dei problemi con le variabili pubbliche è che puoi dichiararle in qualsiasi routine. Questo creerà molte difficoltà nelle operazioni di debug. Per questo motivo dovresti dichiararle solamente nel programma principale. 
Invece di usare variabili pubbliche potresti usare l'oggetto applicazione _app. L'oggetto _app è un oggetto di Visual dBASE che rappresenta la corrente applicazione in esecuzione. Essendo _app globale, esso costituisce un buon posto per mettere quei valori che vuoi che siano sempre disponibili nel programma. Per usare l'oggetto _app, devi semplicemente assegnargli i valori come ad es.:

_app.MyValue = 10 
// oppure 
_app.Ini = New Ini("MyIni.INI") 

Le variabili pubbliche non sono assolutamente utili per aggirare il modello oggetto. Parlerò di questo problema quando affronterò il discorso sulle proprietà. 

Macro e Indirezioni

Le macro sono stringhe di codice che possono essere compilate ed eseguite a runtime. Ad es. 

m_macro = "form.entryfield1" 
o = &m_macro. 
/ / questo è tradotto al volo da dBASE: 
// o = form.entryfield1 
In molti casi usiamo le macro per i comandi dBASE : 
m_macro = "customer.dbf" 
use &m_macro.

Possiamo anche fare quanto su visto usando gli operatori di indirezione () . Quando immetti una variabile tra parentesi, stai "dicendo" a dBASE che vuoi un riferimento indiretto. Ad es.: 

**** 
* metodo che utilizza l'operatore macro 
**** 
private cTable 
cTable = GetFile( "*.dbf" ) 
if not empty(cTable) 
    use &cTable.
&& Operatore macro 
    browse 
endif 

**** 
* metodo che utilizza gli operatori di indirezione 
**** 
local cTable 
cTable = GetFile( "*.dbf" ) 
if not empty(cTable) 
    use ( cTable )
&& operatore di indirezione 
    browse 
endif 

Usando l'indirezione hai alcuni vantaggi. Vale a dire che puoi fare uso di variabili locali che miglioreranno il tempo di esecuzione (1 o 2 ms). 
La tecnica dell'indirezione non funziona in tutte le situazioni dove dovresti usare l'operatore macro, ma funziona con i comandi come: copy to, append from, use, cd, md ecc. 

Variabili e Campi 

Considera il codice seguente: 

private first_name, last_name 
first_name = "Dan" 
last_name = "Howard" 
?"Valori da salvare: ", first_name, last_name 
use contacts 
append blank 
replace first_name with first_name, last_name with last_name 
?"risultato:",first_name, last_name 
use 

Che tipo di output otterrai? 

La risposta è che i campi first_name e last_name saranno lasciati vuoti! 

La ragione è che quando apri una tabella dBASE si creano delle variabili che rappresentano i campi della tabella. I campi avranno la precedenza. Un "work around" è chiamare le tue variabili con nomi diversi rispetto ai nomi di campo. Questo non sempre può essere fattibile. Un approccio migliore  è usare l'operatore alias (->). Usando questo operatore si dice esplicitamente a dBASE a quale variabile o campo ci riferiamo. 

Ci sono 2 modi per migliorare l'esempio su visto: 

cambiare first_name con M->first_name, last_name con M->last_name 
/ / Un modo anche migliore... 
cambiare CONTACTS->first_name con M->first_name, CONTACTS->last_name con M->last_name 

Entrambi i metodi funzioneranno, ma preferisco il secondo perché evita qualsiasi confusione circa l'uso di una variabile o di un campo. Nota che il prefisso M è uno speciale indicatore che dice a dBASE di riferirsi ad una variabile di memoria.

Parametri

I Parametri sono le variabili che passi ad una funzione. Ci sono due modi per dichiarare parametri per una funzione: 

Function MyFunction 
parameters a,b,c 

oppure

Function MyFunction(a,b,c) 

La differenza nei due stili di dichiarazione è che nel primo esempio i parametri saranno creati come variabili private - nel secondo esempio saranno di tipo locale

Ci sono anche 2 modi per chiamare la tua funzione con parametri: 

MyFunction(a,b,c)

oppure

DO MyFunction WITH a,b,c

In più ci sono 2 modi di passare i parametri ad una funzione: per riferimento(indirizzo) o per valore. 

Dalla guida in linea: 

Se passi le variabili per riferimento, la funzione chiamata ha accesso diretto alle variabili. Le sue azioni possono cambiare (sovrascrivere) i valori in quelle variabili. Passa le variabili per riferimento se vuoi che la funzione chiamata modifichi i valori memorizzati nelle variabili che riceve come parametri. 
Se tu passi le variabili per valore, la funzione chiamata utilizzerà una copia dei valori contenuti nelle variabili. Le sue azioni non possono cambiare il contenuto delle variabili. Passa le variabili per valore se vuoi che la funzione chiamata usi i valori delle variabili senza modificarne i loro valori - apposta o fortuitamente - nel sottoprogramma chiamato. 

Nota: Il comportamento di default di dBASE è passare i parametri per riferimento.  

A meno che tu voglia che un sottoprogramma possa modificare i tuoi parametri dovresti sempre passare i parametri per valore. Non essendo questo il comportamento di default di dBASE, per effettuare le chiamate per valore dovrai usare gli operatori di indirezione. Ad es.: 

MyFunction( (a), (b), (c) ) 

Un altro modo per prevenire accidentali modifiche ai tuoi parametri è fare sempre una copia di essi nel sottoprogramma chiamato. Ad es.: 

do MyFunction with a,b,c 

function MyFunction(a,b,c) 
    local x,y,z 
    x = a
// copia il parametro passato alla funzione 
    y = b 
    z = c 

    / / Ora puoi cambiare x,y,z come desideri! 
return 


Nota: Oggetti ed Arrays sono sempre passati per indirizzo. 

Qualche volta è desiderabile passare i parametri per indirizzo. Diciamo ad es. che vuoi una funzione che raddoppierà un qualsiasi valore inviatole: 

n = 10 
Double(n)
// passaggio per riferimento 
?n 
Function Double(x) 
    x = x * 2 
return 

A proposito, lo sapevi che puoi scrivere facilmente funzioni che prendono un numero variabile di parametri? 

È molto facile farlo tramite l'uso delle funzioni argcount() e argvecto(). Copia ed incolla il codice seguente e sperimenta passando alla funzione un qualsiasi numero di parametri: 

// Visual dBASE Versione 7.x  
MultiParam("45",17,true,date()) 

Function MultiParam 
    local j, n 
    private xParam 

    n = argcount() 
    ?"Hai passato " + n + " parametri!" 
    ?"I loro valori sono:" 
    for j = 1 to n 
        xParam = argvector(j) 
        ?"Parametro: " + j + " è " + xParam + " - di tipo: " + type('xParam') 
    next j 
return 

* Visual dBASE Versione 5.x  
MultiParam("45",17,.t.,date()) 

Function MultiParam 
    local j, n 
    private xParam 

    n = argcount() 
    ?"Hai passato " + rtrim(ltrim(str(n))) + " parametri!" 
    ?"I loro valori sono:" 
    for j = 1 to n 
        xParam = argvector(j) 
        ?"Parametro: " + rtrim(ltrim(str(j))) + " è " 
        ??xParam 
        ??" - di tipo: " + type('xParam') 
    next j 
return NULL 

Caratteristica molto elegante - non pensi? Questo funziona anche fra class/endclass.

m = new MultiParam("45",17,true,date()) 

class MultiParam 
    local j, n 
    private xParam 

    n = argcount() 
    ?"Hai passato " + n + " parametri!" 
    ?"I loro valori sono:" 
    for j = 1 to n 
        xParam = argvector(j) 
        ?"Parametro: " + j + " è " + xParam + " - di tipo: " + type('xParam') 
    next j 
endclass 

Che cosa sono le Proprietà? 

Dopo aver trattato abbastanza sulle variabili è tempo di esaminare le proprietà e vedere come esse si differiscono in uso e funzionalità dalle variabili. 
Nell'interesse di questo articolo, quando uso il termine proprietà voglio dire proprietà custom. Le proprietà custom sono proprietà che aggiungi a qualsiasi oggetto predefinito di Visual dBASE. Ad es.: 

Class MyForm of Form 
    this.isOpen = false 
    Function OnOpen 
        this.isOpen := true 
    return 
    Function OnClose 
        this.isOpen := false 
    return 
endclass 

Una domanda sorge spontanea: Perché uso solo proprietà? 

La risposta risiede nella loro visibilità e durata. 

Le proprietà agiscono in modo similare alle variabili con l'eccezione che esse sono "visibili" ad un oggetto e non ad una funzione. Le proprietà esisteranno e saranno accessibili finché l'oggetto esiste. Nell'esempio su visto, la proprietà IsOpen non "muore" alla fine del metodo OnOpen. Essa "vive" fino a che la scheda stessa non sia rilasciata dalla memoria. Questo è un concetto molto importante per capire la filosofia OOP sia di dBASE sia di Windows. 

Il vantaggio che deriva dall'uso di una proprietà è che puoi creare oggetti multipli e ciascuno di esso avrà le proprie impostazioni di dati cosi non ti devi preoccupare se un valore ne ricopre un altro. Ad es.: 

f1 = new MyForm() 
f2 = new MyForm() 
f2.Open() 
?f1.isOpen 
?f2.isOpen 

Entrambi oggetti hanno la stessa proprietà ma ognuno può contenere valori diversi. 
Le proprietà sono un poco più semplici delle variabili perché ne esistono solamente due tipi: proprietà regolari e proprietà protette. 

La proprietà nell'esempio su visto è una proprietà regolare. Questo significa che essa è sempre accessibile fino a quando hai un riferimento all'oggetto di cui essa ne fa parte. Ad es.: 

f = new MyForm() 
f.Open() 
? f.IsOpen 

Le proprietà protette al contrario sono nascoste a qualsiasi cosa al di fuori della classe stessa. Proteggere le proprietà è un buon modo per nascondere il lavorio interno dei tuoi oggetti e prevenirli da essere modificati da un altro oggetto. 
Creare una proprietà protetta è facile. Tutto quello che hai bisogno di fare è usare la parola chiave "protect". Ad es.: 

Class MyForm of Form 
   
PROTECT isOpen 
    this.isOpen = false 
    Function OnOpen 
        this.isOpen := true 
    return 
    Function OnClose 
        this.isOpen := false 
    return 
endclass 

Se  provi il codice seguente: 

f = new MyForm() 
f.Open() 
? f.IsOpen 

Otterrai un errore: “La proprietà non é accessibile” 

Ciò vuole dire che tu puoi usare solamente la proprietà IsOpen fra le dichiarazioni class/endclass. La proprietà anche non apparirà nel modulo ispezione. 

C'è uno piccolo problema con il codice su visto - vale a dire che il modulo "impostazione scheda" rimuove la linea di codice PROTECT isOpen la prossima volta che effettui una operazione di salvataggio. C'è fortunatamente una soluzione elegante a questo problema. Prova il codice seguente:

f = new MyForm() 
f.Open() 
inspect(f) 
Class MyForm of Form 
    Function OnOpen 
        PROTECT isOpen 
        this.isOpen = true 
    return 
    Function OnClose 
        this.isOpen = false 
    return 
endclass

Tieni presente che posso proteggere una proprietà per quanto tempo voglio. Infatti se hai necessità puoi proteggere dinamicamente una proprietà. Manda in esecuzione il codice seguente clicca sulla scheda per visualizzare un secondo modulo ispezione. Nella finestra che visualizza il secondo modulo ispezione la proprietà isOpen è improvvisamente sparita!  

f = new MyForm() 
f.Open() 
inspect(f) 
Class MyForm of Form 
    Function OnOpen 
        this.isOpen = true 
    return 
    Function OnClose 
        this.isOpen = false 
    return 
    Function onLeftMouseUp 
        protect isOpen 
        inspect(this) 
    return 
endclass 

OK ci siamo divertiti abbastanza. Adesso andiamo avanti.

Creare Proprietà 

Le proprietà possono essere create in innumerevoli modi. dBASE usa un modello oggetto dinamico in altre parole gli oggetti possono essere "estesi" dopo che loro sono stati creati. Questo vuol dire che nuove proprietà possono essere aggiunte ad un oggetto in qualsiasi momento. 
Di seguito un esempio che utilizza una proprietà custom per una scheda. 

f = new ConfirmForm() 
f.mdi = .f. 
f.Prompt.Text = "Sei veramente veramente VERAMENTE sicuro che vuoi fare questo????" 
f.ReadModal() 
if f.YesClicked 
    ?"Hai scelto SI! Formattazione dell'Hard Disk...." 
endif 
CLASS confirmFORM OF FORM 
    this.AutoCenter = .T. 
    this.Text = "Confermare Prego" 
    this.Left = 54.166 
    this.Top = 7.4697 
    this.Height = 7.5879 
    this.Width = 59.166 

DEFINE TEXT PROMPT OF THIS; 
    PROPERTY; 
    Alignment 10,; 
    Text "Sei veramente veramente veramente sicuro che vuoi fare questo????",; 
    FontSize 12,; 
    Left 1,; 
    FontBold .F.,; 
    Top 0.9404,; 
    Height 4.7061,; 
    Width 56 

DEFINE PUSHBUTTON YESBUTTON OF THIS; 
    PROPERTY; 
    Text "&SI",; 
    Left 2,; 
    FontBold .F.,; 
    Top 6.1172,; 
    OnClick CLASS::YESBUTTON_ONCLICK,; 
    Group .T.,; 
    Height 1.1172,; 
    Width 11.833 

DEFINE PUSHBUTTON NOBUTTON OF THIS; 
    PROPERTY; 
    Text "&No",; 
    Left 46,; 
    FontBold .F.,; 
    Top 6.1172,; 
    OnClick CLASS::NOBUTTON_ONCLICK,; 
    Group .T.,; 
    Height 1.1172,; 
    Width 11.833 

Function ReadModal 
 
   * Aggiungerò qui la mia proprietà custom. 
    form.YesClicked = .f. 
return Super::ReadModal() 

Procedure YESBUTTON_OnClick 
    form.YesClicked = .t. 
    form.Close() 
return 

Procedure NOBUTTON_OnClick 
    form.Close() 
return 

ENDCLASS 

In questo esempio ho usato il metodo ReadModal della scheda per creare una proprietà custom chiamata YesClicked. Osserva che essendo una proprietà, posso accedere da qualsiasi metodo definito nella classe. 
Normalmente, puoi creare queste proprietà custom nella parte costruttore della classe ma nel caso della scheda uso i metodi Open o ReadModal così che impostazione scheda terrà il mio codice. 

Usando le Proprietà 

Le proprietà custom sono specialmente utili quando hai bisogno di condividere informazioni con funzioni diverse nella tua classe. ad es. 

Class MyForm of Form 
    Function onOpen 
        form.recordSaved = false 
    return 
    Function SaveButton_onClick 
        form.rowset.save() 
        form.recordSaved := true 
    return 
    Function canClose 
        local lCanClose 
        lCanClose = true 
        if not form.recordSaved 
            msgbox("Prima salva il record!") 
            lCanClose := false 
        endif 
    return ( lCanClose ) 
endclass 

per fare questo potresti usare una variabile pubblica. Ad es.: 

Class MyForm of Form 
    Function onOpen 
        public recordSaved 
        recordSaved = false 
    return     
    Function SaveButton_onClick 
        form.rowset.save() 
        recordSaved := true 
    return 
    Function canClose 
        local lCanClose 
        lCanClose = true 
        if not recordSaved 
            msgbox("Prima salva il record!") 
            lCanClose := false 
        endif 
    return ( lCanClose ) 
endclass 


Ma cosa c'è di sbagliato in questo codice? 

Nulla realmente. Funzionerà se la tua applicazione ha solamente una scheda. 

Cosa accadrebbe se i tuoi utenti volessero un applicazione MDI (Multiple Document Interface)? 

Che cosa accadrebbe se loro volessero potere aprire 4 o 5 copie della stessa scheda per esaminare/modificare i dati? 

Saresti veramente incasinato. Ciascuna scheda ricoprirebbe gli altri valori “recordSaved”. Non sarai mai sicuro circa quale scheda stai usando! 
Il codice su è un esempio abbastanza semplice, ma questo è quello che volevo farti notare quando parlavo di fare attenzione sulla possibilità di aggirare il modello dell'oggetto. 

Utilizzando l'idea del dQUIZ di Peter Rorlick, ti mostrerò alcuni esempi di codice. Tenta di indovinare la soluzione prima di guardare la risposta. Non barare! :-) 
Gotcha #1 

Guarda l'esempio seguente: quale sarà l'output generato? 

* Gotcha # 1 

a() 
function a 
    ?program() 
    for j = 1 to 10 
            ?j 
            b() 
    next j 
return 

function b 
    ?program() 
    for j = 1 to 10 
            ?j 
    next j 
return 

Risposta #1 

Gotcha #2 
Osserva il codice seguente quale sarà l'output generato? : (questo è facile) 

* Gotcha #2 

local object1, object2 

object1 = New MyObject() 
object1.SetValue(10) 

object2 = New MyObject() 
object2.SetValue(20) 

?object1.GetValue() 
?object2.GetValue() 

Class MyObject 
    public nValue 
    Function SetValue(n) 
        nValue = n 
    return 
    Function GetValue 
    return ( nValue ) 
endclass 


Risposta #2 

Gotcha #3 
Copia & incolla il codice seguente. Quali risultati otterrai? 


local string, x 
string = "Dan Howard" 
?"Valore Iniziale di STRING: " + string 
x = upper(string) 
?"Valore di STRING dopo la chiamata alla funzione upper: " + string 
x = MyUpper(string) 
?"Valore di STRING dopo la chiamata alla funzione MYupper: " + string 

Function MyUpper(cStr) 
    cStr = upper(cStr) 
return (cStr) 

Answer #3 

Gotcha #4 
Cosa si verificherà nel codice seguente? 

o = new MyObject() 
o.Display() 

class MyObject 
       private hello 
        hello = "hello" 

        function Display 
            ?hello 
        return null 
endclass 

Risposta #4 

Tips 

Generalmente, non creare mai variabili pubbliche o private; usa invece variabili locali. Evita il più possibile la dichiarazione parameters, usa parametri locali invece. (eccetto se hai bisogno chiaramente delle macro) 
Se una sotto routine (funzione) ha bisogno di accedere ad una variabile, passala come un parametro invece di fare uso di variabile private. 
quando è opportuno sforzati di creare proprietà custom invece di variabili. 
Usa proprietà custom dell'oggetto _app invece di variabili pubbliche. Ma con un buon OOP approccio, valori che hanno visibilità globale e durata permanente sono necessari raramente, - così sforzati di evitarli. 
Conclusione 
Bene spero di averti dato abbastanza da pensare. Le cose ricordare sono: 
Usa solamente variabili pubbliche quando hai a che fare con cose specifiche alle applicazioni stesse. 
Usa proprietà quando hai a che fare con oggetti. 
Usa variabili quando hai a che fare con funzioni. 


Buon divertimento