OOP.HOW
(c) 1995 A.A.Katz, All Rights Reserved.
By A. A. Katz
Muoversi nella programmazione OO, é spesso difficile anche per programmatori esperti. Prima di OOP, imparare un nuovo linguaggio, consisteva soltanto nell'impadronirsi della nuova sintassi. OOP, richiede molto più. Un maggiore sforzo nel modo di immaginare i programmi, ed il relativo codice. Devo ammettere, che il processo di apprendimento é difficile. Ma i benefici sono talmente enormi, da compensare il tempo impiegato, ad imparare questa nuova metodologia di programmazione.
Visual dBase 5.x, ha una delle più semplici, ed allo stesso tempo più eleganti implementazioni, di OOP. E' la piattaforma perfetta, per il primo progetto Object-Oriented.
OOP è una metodologia di programmazione, che fa uso di "oggetti".Gli oggetti si possono definire come delle entità, che hanno "in se" determinati attributi (proprietà) e determinati comportamenti (metodi).
Quali differenze con le architetture di programmazione precedenti?
Se hai già programmato, probabilmente hai usato metodi procedurali. I tuoi programmi cominciavano dal punto "A", andavano al punto "B" e ritornavano al punto "A". L'interfaccia utente, era basata, su una struttura a menu gerarchico. L'utente utilizzava il programma, tramite menu innestati e tornava indietro, utilizzando il tasto <ESC> o qualche altro tasto, predefinito dal programma.
In OOP, gli oggetti, sono "lanciati", creati, attivati - ed il controllo e nelle mani dell'utente finale. Non esiste un modo "obbligato" per muoversi nel programma.
Ciascun oggetto, ha la sua propria "vita" indipendente da tutti gli altri oggetti.
Per Il Programmatore: Il beneficio principale (fra i tanti), che OOP offre al programmatore, è la "riutilizzabilità". Se ben progettati, gli oggetti possono essere riutilizzati, in qualsiasi programma senza adattamenti. Gli oggetti non richiedono: dichiarazione di variabili, chiamate a procedure, ecc.
Teoricamente, potresti scrivere, interi programmi, con poco o addirittura nessun codice. Dovresti appena combinare gli oggetti, insieme a poche proprietà e via in esecuzione....
Per L'Utente: In genere, i programmi sviluppati con OOP, danno agli utenti diversi "poteri". Ciascun utente, può personalizzare il programma, per adattarlo al loro ambiente di lavoro, tramite la selezione degli oggetti, in funzione del loro compito e delle loro abitudini, e non, secondo uno schema rigido condizionato da un menu gerarchico.
La programmazione OO, è basata su una manciata di concetti chiave.Devi conoscerli bene, per creare classi di oggetti effettivamente riutilizzabili.
Incapsulazione
Non puoi influire sul controllo degli oggetti da parte del tuo utente. Non hai assolutamente idea, di quanti oggetti, di quale genere, il tuo utente visualizzerà sullo schermo in un dato momento. Il migliore modo per assicurare che tutto lavorerà insieme, malgrado le scelte dell'utente, è garantire che ogni oggetto lavorerà solo ed indipendentemente. Ciascun oggetto, deve contenere tutti i suoi dati e le sue procedure, ed essere completamente isolato da ogni altro oggetto.
Non permettere che un oggetto "ricopra" un altro. O che una procedura di un oggetto, vada in esecuzione con i dati di un altro oggetto! N.B. Quando ci riferiamo ai dati di un oggetto, non stiamo parlando delle tabelle dati.
Gli oggetti possono, e spesso fanno, condividere le tabelle. I dati di un oggetto sono i valori memorizzati nelle proprietà dell'oggetto.
E' importante isolare questi dati.
Se hai sullo schermo due "finestre Client" , ciascuna finestra ha i suoi dati e le sue caratteristiche, protette l'una dall'altra.
Isolare queste proprietà e questi comportamenti dicesi "Incapsulazione".
Ereditarietà.
Gli oggetti, hanno la capacità di ereditare attributi (proprietà) e comportamenti (metodi), da altri oggetti. Questo è un aspetto delicato, dal punto di vista della riutilizzabilità. Per riutilizzabilità si intende, la capacità di modificare un oggetto in una specifica applicazione, senza doverlo riscrivere.
Presumi, per esempio, di creare un oggetto AUTOMOBILE. Esso possiede alcune proprietà (come i pneumatici, il motore ecc) ed alcuni comportamenti (partenza,frena, fai il pieno ecc) che possono essere ereditabili.
Infatti, usando OOP, puoi creare un nuovo oggetto, chiamato ELICOTTERO derivato da AUTOMOBILE. Il nuovo oggetto ELICOTTERO, possiede tutte le proprietà ed i comportamenti di AUTOMOBILE, con in più alcune proprietà (rotore) ed alcuni comportamenti (decolla) specifici, ovviamente ad un elicottero.
Si dice che ELICOTTERO ha ereditato le proprietà (pneumatici, motore) ed i comportamenti (parti,arresta) da AUTOMOBILE.
Tramite l'eredità, la produttività viene enormemente migliorata. Usando OOP, non dovresti avere la necessità di "reinventare la ruota".
Polimorfismo.
Gli oggetti, possono modificare i comportamenti e le proprietà che hanno ereditato.
L'oggetto "figlio", può ridefinire i comportamenti "parti" e "arresta" di AUTOMOBILE, più opportunamente per ELICOTTERO, cambiando questi comportamenti in "decolla" e "atterra."
Il Polimorfismo (che letteralmente significa, "forme multiple") migliora la riutilizzabilità degli oggetti. Non devi scartare a priori, che l'oggetto AUTOMOBILE possa essere "genitore" (parent) per l'oggetto ELICOTTERO, solo perché le proprietà "parti" e "arresta" (di AUTOMOBILE) non descrivono accuratamente il comportamento di ELICOTTERO.
E' perfettamente naturale, quando si studiano nuovi concetti, cercare di trovare analogie in quello che si é studiato in passato. In questo caso non farlo!
Ti verrà più facile comprendere la programmazione OO, se hai familiarità con i relativi termini. Perciò, può aiutarti, prima di proseguire,un vocabolario di programmazione Object-Oriented:
Class
Una Classe è la definizione di un oggetto.
CLASS Automobile &&classe
This.Tires = 'Radial'
This.Engine = 'Six Cylinder'
This.Trunk = 'Hatchback'
This.Start = CLASS::Turn key
This.Stop = CLASS::Press Brake
ENDCLASS
Suggerimento:
Molti principianti confondono una CLASSE con un programma o una procedura.Una CLASSE non è codice eseguibile. E' solo una "copia" un "modello" di un determinato oggetto. |
SubClass
Una classe derivata "figlia" , ereditata da un'altra classe.
CLASS Helicopter of Automobile && subclass
This.Rotors = 6
This.Start = CLASS::Take_Off
This.Stop = CLASS::Land
ENDCLASS
SuperClass
La classe "genitore" di una sottoclasse. Ad esempio AUTOMOBILE è la "SuperClass" di ELICOTTERO.
Proprietà
Le proprietà sono simili alle variabili, infatti, sono usate per memorizzare informazioni. Una proprietà Cognome agisce nello stesso modo di una variabile Cognome - cioè provvede a memorizzare spazio per i vari possibili Cognomi. Comunque, diversamente dalle variabili, le proprietà non "appartengono" ai programmi o alle procedure, ma, appartengono all'oggetto.
Le proprietà definiscono le caratteristiche (gli attributi) di un oggetto.
CLASS Helicopter of Automobile
This.Rotors = 6 &&Proprietà
This.Tires = 'Pirelli'
This.Engine = 'Jet'
ENDCLASS
Il passaggio meraviglioso, dalla programmazione procedurale alla programmazione OO, è il modo in cui le proprietà si riflettono sull'oggetto.Se volevi cambiare il valore di un campo, dovevi immettere il nuovo valore e poi rivisualizzarlo:
cMiaVar = "Ciao"
@ 2,1 say cMiaVar
Nella programmazione OO, la modifica è incapsulata, é un comportamento dell'oggetto:
OO: This.Value = 'Ciao'
Gli effetti di una modifica di una proprietà, si riflettono automaticamente sullo schermo, non hai bisogno dell' istruzione
@2,1 say cMiaVar, ciò fa risparmiare molto codice .
Metodo
Un metodo, è il codice che esegue il "comportamento" di un oggetto. Tale "comportamento" viene implementato tramite le procedure e le funzioni. I metodi sono procedure e funzioni che appartengono ad un oggetto.
CLASS HELICOPTER OF AUTOMOBILE
This.Start = CLASS::TakeOff
PROCEDURE Take Off &&Metodo
if CLASS::Checklist()
if CLASS::TurnEngineOn()
if CLASS::Taxi()
if CLASS::GetClearance()
CLASS::LiftOff()
endif
endif
endif
endif
ENDCLASS
Istanza
L'attuale "oggetto" derivato da una Classe.
Define AlansCar of Automobile &&istanza
Define JanesHelicopter of HELICOPTER
OO supporta le istanze multiple simultaneamente della stessa classe.
Define AlansCar of Automobile &&Istanze multiple
Define JanesCar of Automobile
Define OurFamilyCar of Automobile
MyCar = New Automobile() &&Istanze multiple utilizzo New invece di Define
Le istanze sono gli oggetti che l'utente finale vede e usa. Le classi e le sottoclassi, sono gli strumenti di programmazione che usi per crearle.
Istanziare
Creare una singola istanza di una classe in memoria.
In altre parole, si costruisce un oggetto dalla definizione di classe. Questo è simile alla "costruzione di una casa." La classe è il "modello" il "progetto".
Quando crei un'istanza, Visual dBase costruisce "la casa" dal "progetto" fornito nella definizione di Classe.
DEFINE AlansCar of Automobile &&istanza
oppure
AlansCar = New Automobile()
Oggetti Contenitori
Alcuni oggetti hanno la capacità di contenere altri oggetti, ad esempio l''oggetto Scheda.
Una scheda può contenere pulsanti, oggetti browse,oggetti editor, etc.
Ovviamente, un pulsante (pushbutton), il quale non è un oggetto contenitore, non può contenere una scheda o un browse o un editor.
Classi standard
Visual dBase, include circa 30 classi standard dalle quali puoi creare istanze o sottoclassi custom.
Schede, oggetti array e controlli schermo come pushbuttons, entryfields, browses e checkboxes sono tutte classi standard.
Classe base
La Classe Base è la "copia" dell'oggetto Scheda che è usata ogni volta che crei una nuova scheda usando "Impostazione Scheda".
Visual dBase, ha una nuova stupefacente capacità che ti lascia usare le proprie schede come Classe Base per nuove schede.
Questo è estremamente utile per standardizzare il "look" e l'uso di un'applicazione.
La tua Classe Base può includere pulsanti di una speedbar, titoli, barre di stato, rettangoli ed ogni altro controllo che desideri appaia su tutte le nuove schede.
Quando definisci la tua Classe Base, le schede che vengono generate sono sottoclassi della terza generazione:
1. Form &&Classe base Predefinita
2. Class AUTOMOBILE of Form() && La tua nuova classe base la quale è una sottoclasse di form
3. Class HELICOPTER of AUTOMOBILE && La tua nuova classe, derivata Automobile, che a sua volta era derivata da form
Classi Custom
Visual dBase ti permette di creare classi custom da classi "scratch", da classi standard o da altre classi custom.
Class Automobile && da scratch
Class Automobile(f,n) of Form(f,n) && da Classi base
Class Helicopter(f,n) of Automobile(f,n) && Da Classi custom
Le classi che crei sono chiamate Classi Custom per distinguerle dalle Classi standard predefinite.
Costruttore
Il Codice Costruttore è quella parte della classe "modello" per gli oggetti. Include tutte proprietà ed i loro valori. Non include i metodi della classe (procedure e funzioni). Nel caso di un oggetto contenitore, come la scheda, il codice costruttore include anche la definizione di tutti gli oggetti contenuti nella scheda.
Non puoi aggiungere nuove proprietà o metodi nel codice Costruttore di un oggetto usato con gli strumenti Two-Way come Impostazione Scheda e Impostazione Menu. Questa area è riservata per gli strumenti. Puoi, comunque,impostare valori o includere o rimuovere proprietà predefinite.
Per aggiungere nuove proprietà, devi costruirle dentro classi custom o aggiungerle dinamicamente durante un evento come ad esempio OnOpen.
CLASS Myform(f,n) of Form(f,n)
This.Top = 2
This.Left = 2
This.Width = 40
This.Height = 20
DEFINE PUSHBUTTON PUSHBUTTON1 OF THIS;
PROPERTY; && Costruttore
Top 3,;
Left 3,;
Width 5,;
Height 1.06,;
ColorNormal "W+/N"
PROCEDURE FORM_OnOpen && Metodo
This.FormNumber = 2
&& La procedura FORM_OnOpen si definisce metodo quando è inclusa
&& nella definizione dei metodi della classe. Qualche volta è anche chiamata "membro"
&& This.FormNumber è una proprietà custom della scheda
ENDCLASS
Programmazione "guidata da eventi"
La chiave di volta dai linguaggi procedurali in ambiente DOS all' ambiente Windows e Visual dBase è la programmazione "guidata da eventi".Questo non è un concetto OOP. Nella programmazione "guidata da eventi" l'applicazione diviene reattiva, cioè al verificarsi di qualcosa (evento) essa reagisce ed esegue il comportamento (metodo) associato a quell'evento.
Un evento può essere un click del mouse (OnClick), la pressione di un tasto. Può essere passare ad un altro programma o finestra (onGotFocus, OnLostFocus). Può essere un evento interno di Visual dBase, come la convalida di una immissione di dati (Valid) o permettere l'accesso ad un controllo (When).
Un programma "guidato da eventi" consiste di solo due elementi fondamentali:
1. Opportunità per input/eventi
2. "Cosa-se"
Il tuo codice di interfaccia utente consiste di "opportunità" per gli eventi:Schede, pushbuttons, menu, oggetti browse,editors, entryfields, etc.
Il tuo codice "cosa-se" consiste di un "gestore evento".
Visual dBase, cattura un evento come un click del mouse, guarda se esiste un "gestore evento" per quel particolare evento ed oggetto. Se c'è, Visual dbase "attiva" l'evento - lancia cioè la procedura o la funzione collegata all'evento.
per costruire un gestore evento, devi semplicemente collegare il tuo codice (metodo) all'oggetto che attiva l'evento:
CLASS MyForm(f,n) of Form(f,n)
This.top = 2
This.left = 2
This.Height = 20
This.Width = 40
Define PUSHBUTTON1 of This; &&oggetto
Property;
Top 4,;
Width 20,;
Text 'Press this button',;
OnClick CLASS::PUSHBUTTON1_OnClick && Link al gestore evento
PROCEDURE PUSHBUTTON1_OnClick &&metodo gestore evento
This.ColorNormal = 'R/W'
This.Text = 'Button is Pressed'
ENDCLASS
Ciascun oggetto standard, ha i suoi propri eventi predefiniti. Per un elenco di eventi per ciascuna classe di oggetto, seleziona l'oggetto in impostazione scheda, premi il tasto destro del mouse e dal menu pop up seleziona "ispezione" quindi seleziona la pagina eventi, la quale elenca gli eventi disponibili per l'oggetto selezionato.
Di seguito viene indicato un elenco molto parziale di eventi e quando sono attivati:
OnOpen (quando una scheda é aperta)
OnClick (quando si clicca il tasto sinistro del mouse)
OnGotFocus (Esegue una subroutine quando un oggetto viene focalizzato)
OnLostFocus (Esegue una subroutine quando il fuoco viene rimosso da un oggetto)
Valid (Specifica una condizione che deve esser vera (.T.) prima che l'utente possa spostare il fuoco da un oggetto.)
When (Specifica una condizione che deve essere vera (.T.) prima che l'utente possa focalizzare un oggetto)
OnClose (quando una scheda viene chiusa)
CanClose (Esegue una subroutine che determina se una scheda può essere chiusa, quando viene effettuato un tentativo di chiusura della scheda)
CanNavigate (Esegue una subroutine che determina se il puntatore ai record può spostarsi da un record a un altro)
OnChange (Esegue una subroutine quando l'utente modifica il valore visualizzato in un oggetto)
OnLeftDblClick (quando l'utente effettua un doppio click sul tasto sinistro del mouse)
OnSelChange (Esegue una subroutine quando l'evidenziazione viene spostata da una voce a un'altra in una casella di riepilogo o in un separatore)
Suggerimento:
L'inclinazione iniziale dei programmatori procedurali è cercare di usare Visual dBase e Windows per emulare le loro precedenti strategie procedurali. Una volta ancora, non farlo! Non otterrai i benefici di OOP, windows e Visual dBase. |
I Calcoli sono fatti spesso dall'evento OnChange.I records sono aggiunti, salvati o abbandonati dall'evento evento OnClick di un pulsante o da un evento CanNavigate di un oggetto Browse. Nuovi oggetti sono lanciati da un evento OnClick di un menu o di un pulsante.
La convalida dei dati, è anche gestita differentemente nella programmazione guidata da eventi. Hai probabilmente usato convalidare ciascun campo prima di passare al prossimo.Nei programmi controllati dagli eventi non esiste una rigida sequenza di azioni. Il modello controllato da eventi fa la maggior parte dell'operazioni di convalida in un singolo evento OnClick di un pulsante "OK" o "Salva".
Guarda tutti i dati degli oggetti, non a un campo alla volta per compiere la convalida dei dati:
PROCEDURE OKBUTTON_OnClick
if empty(Form.Entyfield1.Value)
MsgBox('Spiacente, Richiesto Numero Cliente!')
Form.Entryfield1.SetFocus()
elseif empty(Form.Entryfield2.value)
MsgBox('Spiacente, Richiesto Numero Cliente!')
Form.Entryfield2.SetFocus()
elseif etc....
else
Select MyTable
Form.SaveRecord()
endif
Se hai necessità di avere istanze multiple di ELICOTTERO, dovrai poter distinguere tra MIOELICOTTERO e TUOELICOTTERO.
Le istanze nella vita reale sono identificate da nomi, numeri di serie ecc.
Una istanza di una classe, è distinguibile da un' altra tramite la propria variabile di riferimento all'istanza - un unico "nome" per ciascuna istanza di ciascuna classe.
Il "nome" di un oggetto è qualche volta anche chiamato Variabile di Riferimento Oggetto.
Come la maggior parte dei riferimenti indiretti, in programmazione (variabili, campi, etc.), la Variabile di riferimento all'istanza contiene l' indirizzo dell'oggetto, non l'oggetto stesso.
oMyHelo = New Helicopter()
Nella linea di codice precedente, Visual dBase crea un nuovo oggetto Helicopter e memorizza il suo indirizzo nella variabile oMyHelo.
Una volta che hai ottenuto da un oggetto, la sua Variabile di riferimento all' istanza(in altre parole il suo indirizzo), puoi "parlare" con l'oggetto direttamente - cambiare le sue proprietà, aggiungere proprietà nuove, attivare i suoi metodi:
oMyHelo = New Helicopter() && Crea una nuova istanza
oMyHelo.TailNumber = 'A23456' && Definisce una nuova proprietà
oMyHelo.Entryfield1.Value = 1 && imposta un valore di default
oMyHelo.Open() && Apre la scheda
oMyHelo.Entryfield1.SetFocus() &&attiva il metodo SetFocus()
Come puoi osservare la variabile di riferimento all'istanza ti da un enorme controllo sull'oggetto.
Puoi inizializzare valori di default, prima dell'apertura, rendere visibili o invisibili alcuni oggetti, abilitare o disabilitare altri. Infatti puoi fare qualsiasi cosa dall'esterno o dall'interno dell'oggetto fino a quando hai la variabile di riferimento all'istanza.
La variabile di riferimento all'istanza é una variabile come ogni altra. Puoi passarla come un parametro memorizzarla in un altra variabile
cCurrHelo= oMyHelo
e rilasciarla.
Questo ovviamente ha un "costo". La variabile di riferimento all'istanza è anche visibile come qualsiasi altra variabile.
E, se la variabile di riferimento all'istanza va fuori "portata", hai perso tutte le possibilità di impostare e leggere le proprietà, o di attivare i metodi dall'esterno dell'oggetto.
Se l'istanza di riferimento è una variabile privata, scompare quando la procedura corrente termina, anche se l'oggetto è ancora attivo sullo schermo!
Un altra potenziale "buca", quando stai usando una variabile per memorizzare l'indirizzo di una istanza, è la sovra scrittura della stessa quando tenti di creare istanze multiple:
oMyHelo = New Helicopter() &&Prima Istanza
oMyHelo = New Helicopter() &&Seconda Istanza
La seconda istanza ricoprirà la prima, di conseguenza la prima resta orfana - e non può essere più indirizzata in nessun modo.
Impostazione Scheda, gestisce questo problema, aprendo automaticamente tutte le schede con una variabile LOCALE. Dopo tutto puoi avere un numero illimitato di copie di una variabile LOCALE:
LOCAL f
f = New Myform()
f.Open()
Questo fatto ha anche un aspetto "limitativo". Poiché "f" è LOCALE è solamente visibile alla procedura nella quale è stata dichiarata, nessuno altro oggetto, procedura o funzione può indirizzare la scheda "f."
Soluzione: Cerca di memorizzare le tue Istanze di Riferimento (indirizzi dell'oggetto) in proprietà il più possibile. Ricorda che le proprietà sono visibili agli oggetti, non alle procedure.
Procedure HeliLookupButton_OnClick
Set procedure to c:\HeliLook.Wfm Additive
Form.oLookup = New HeliLookForm() && Istanza di Riferimento memorizzata i una proprietà custom di una scheda
Form.oLookup.Open()
Se hai bisogno di aprire e gestire istanze multiple di una scheda, a richiesta dell'utente, puoi anche memorizzare le tue istanze di riferimento in un array. Oppure, puoi "attaccare" le istanze di riferimento direttamente all'oggetto applicazione di dBase (_app) per avere un campo di definizione "PUBLIC".
(Vedi nelle sezioni seguenti: Form, This., Class::, Super:: and _app)
Un caso comune nel quale le schede possono avere bisogno di "parlare" tra di loro, è ad esempio, una scheda "figlia" di controllo (lookup). Dove la scheda figlia deve impostare una proprietà nella scheda genitore quando un controllo (lookup) è completato con successo. Per fare questo, la "figlia" deve conoscere l'istanza di riferimento del genitore (o semplicemente l'indirizzo).
Il modo più facile per "passare" l' "indirizzo" del genitore è creare una proprietà custom nella scheda "figlia" prima di essere lanciata - e memorizzare in essa il riferimento del genitore:
Nella Scheda "Genitore"
Procedure CustomerLookUpButton_OnClick
Set Proc to C:\CustLook.Wfm
Form.oChild = New CustLookForm()
Form.oChild.ParentName = Form && Memorizza l'indirizzo della scheda genitore
&& in una proprietà custom della scheda figlia
Form.oChild.ReadModal() && Apertura modale
Nella scheda "figlia"
Procedure OKButton_OnClick
Form.ParentName.Entryfield1.Value = Customer->CustNo
Form.Close()
La capacità di una scheda di parlare con un altra è chiamata "Comunicazione tra processi."
Form, This, Class::, Super::, _app
Tutte le architetture di programmazione, forniscono elementi tramite i quali, il programmatore può riferirsi durante la fase di progettazione dell'applicazione, riferimenti che non saranno conosciuti mentre il programma è in esecuzione.
Quando scrivi un programma, non hai idea di quali dati l'utente immetterà.
Così il tuo linguaggio ti da campi,variabili,array, macro-espansioni e codeblocks come un modo di riferirsi a dati "sconosciuti durante la fase di progettazione".
Anche gli oggetti sono "ignoti durante la fase di progettazione". Come programmatore, tu progetti le classi dalle quali gli oggetti saranno creati. Ma, è l'utente che determinerà quante istanze di quale oggetti saranno sullo schermo in fase di esecuzione.
Visual dBase, fornisce speciali elementi di linguaggio OOP che ti permetteranno di riferirti ad oggetti non ancora creati:
Form
"Form" è una variabile predefinita che si riferisce all'istanza di riferimento della scheda corrente.
Al programmatore, fornisce un conveniente riferimento all' oggetto contenitore durante la fase di progettazione, nonostante l'oggetto non sia stato istanziato.
Può essere usato all'interno di una scheda per fare riferimento a se stessa, ma può essere passato come proprietà o parametro ad altre schede, procedure e funzioni.
Do MyProc with Form
oppure
ReCalc(Form)
Si presume che istanzi la scheda con: oMyHelo = New Helicopter().
Quando usi "form" dall'interno della scheda, form é uguale a oMyHelo.
oMyHelo = New Helicopter()
Class Helicopter(f,n) of Automobile(f,n)
This.Width = 40
This.Height = 40
This.OnOpen = FORM_OnOpen
Procedure FORM_OnOpen
Form.Height = 60 &&Form=oMyHelo
Endclass
This
"This", è un' altra generica variabile predefinita, che memorizza un riferimento oggetto. Diversamente da Form, la quale si applica solo all'oggetto contenitore, "This" può riferirsi a qualsiasi oggetto.
Se sei nell'area di definizione della scheda
This = Form
Se sei nella definizione di un controllo dentro una scheda:
This = Form
Se sei in un metodo (procedura o funzione fra una classe):
This= il Controllo che ha chiamato questo Metodo
Esempio:
Class MyForm of Form
This.Width = 24 && this si riferisce alla scheda (form)
This.OnOpen = Form_OnOpen
Define Text MyText of This; &&Si riferisce alla scheda
Property;
Width This.Width,; && Si riferisce alla scheda
OnOpen MyText_OnOpen
Procedure Form_OnOpen
This.Width = 40 && Si riferisce alla scheda
Procedure MyText_OnOpen
This.Width = 10 && Si riferisce a MyText
Class:: e Super::
Class:: e Super:: sono chiamati "Operatori di definizione del campo di azione". Questi operatori "dicono" a Visual dBase dove cercare un metodo. "Class:: MyProc" dice a Visual dBase di guardare SOLO nella classe corrente per il metodo "MyProc.", di non guardare dentro altre classi, o in UDF con lo stesso nome e di non cercare in una procedura esterna o nella SuperClass (se c'è una).
"Super:: MyProc" dice a Visual dBase di guardare solo nella SuperClasse della classe corrente, non nella classe corrente o qualche altra UDF o procedura. Questi due operatori, Super:: e Class:: sono fondamentali dal punto di vista del polimorfismo (la capacità di avere la priorità di un metodo di una classe con un altro).
Tramite l'uso di questi Operatori di definizione del campo di azione, puoi esplicitamente "dire" a Visual dBase quale metodo chiamare:
Class HELICOPTER of AUTOMBILE
...
...
Define Pushbutton StartButton of This;
Property;
OnClick CLASS::Start && Esegue il metodo definito nella classe elicottero (corrente)
&&"start" method.
OnClick SUPER::Start && Esegue il metodo definito nella classe automobile (livello superiore)
&&"start" method.
Endclass
Suggerimento: "Super::" si riferisce genericamente ai metodi di una classe di "livello superiore".Se ELICOTTERO nell'esempio su visto è su una scheda:
Define Automobile HELICOPTER of This;
Property;
OnClick SUPER::OnClick
"Super::" si riferisce alla scheda. O al meno controlla se la scheda
possiede un evento OnClick. Se cosi non fosse, Visual dBase cercherà nella gerarchia di classi definita fino a quando troverà un metodo con il giusto nome.
Forse un chiarimento più accurato per Super:: potrebbe essere "il prossimo livello che Visual dBase trova".
Questo può essere molto utile quando hai una classe custom basata a sua volta su un 'altra classe custom e così via.
_app
"_app" è il nome dell'oggetto applicazione predefinito di Visual dBase. Questo oggetto è il "genitore" del tuo programma. E' sempre visibile fino a che il tuo programma è in esecuzione.
Il perché di questa visibilità ( _app, è un oggetto), risiede nel fatto che puoi usare proprietà custom di _app invece di variabili PUBBLICHE.
Ogni proprietà custom di _app sarà indirizzabile in tutto il tuo programma.
Diciamo che se stai scrivendo un programma, che ha solo una singola istanza per ciascuna scheda Non ti devi preoccupare di usare un array oppure di sovrascrivere variabili di Istanza.
Puoi "attaccare" la tua Istanza di riferimento nell'oggetto _app di Visual dBase:
_app.oMyHelo = New Helicopter()
Adesso hai la garanzia che "oMyHelo" sarà "accessibile" in tutto il tuo programma, visibile a ogni oggetto, procedura e funzione.
E se hai bisogno di un array per memorizzare le tue Variabili di Riferimento all'istanza, puoi anche "attaccarle" nell'oggetto _app:
_app.aForms = New Array(1)
_app.aForms[1] = New Helicopter()
_app.aForms[1].Open()
dove anche sarà visibile a tutti oggetti, procedure e funzioni.
Gli oggetti "consumano" memoria. E non solo memoria "normale", ma risorse GDI, le quali sono molto scarse in Windows. La maggior parte "dell'economia domestica" (pulizia) è gestita automaticamente da Visual dBase. Per esempio, quando in memoria non ci sono riferimenti ad un oggetto, Visual dBase distrugge l'oggetto per liberare memoria.
Puoi distruggere esplicitamente un oggetto in due modi:
1. Se hai un metodo Release(), chiamalo per rimuovere l'oggetto dalla memoria.
2. Distruggi la variabile di riferimento all'istanza (oggetto) e Visual dBase rimuoverà l'oggetto automaticamente.
Esempi:
oMyHelo.Release() && Chiama il metodo release
Release All Like oMyCustom &&Rilascia l'istanza di riferimento
_app.aForms[1] = '' && sovra scrive l'istanza di riferimento
Una volta che l'oggetto è rilasciato, non hai bisogno della definizione di classe in memoria . Rimuovila con:
Close Procedure Helicopter.WFM
Usare le Sessioni per Incapsulare
Sappiamo che le proprietà sono Incapsulate dentro i loro oggetti. Sappiamo altresì, che dobbiamo isolare la Variabile di Riferimento all'Istanza, prima che tu possa avere istanze multiple di un oggetto, per evitare sovra scritture.
Ma per le tabelle dati bisogna fare un altro discorso. Le tabelle sono "accessibili" nelle loro aree di lavoro - e non da qualche oggetto. Ancora, c'è un dato importante - il puntatore al record - ha bisogno anche di essere incapsulato.
Presumi che il tuo utente visualizzi contemporaneamente tre schede Elicottero. Presumi, anche, che ciascuna scheda ha un oggetto Browse.
La scheda Numero Tre è in primo piano, quando l'utente clicca sulla barra di scorrimento,per cambiare il record attivo. A meno che, tu non faccia qualcosa per evitarlo, spostandosi su un altro record nella scheda elicottero tre, cambierà anche il record nella scheda elicottero due e elicottero uno.
Quindi, il puntatore al record deve essere incapsulato- protetto dal movimento del puntatore record in un altro oggetto elicottero.
Visual dBase, provvede con una caratteristica pulita, per gestire questa situazione, chiamata Sessioni (Session) .
Le Sessioni, essenzialmente creano un nuovo utente. Ciascuno utente, ha le proprie aree di lavoro, puntatori al record, aliases e variabili d'ambiente. Per creare una Sessione prima di lanciare un oggetto, incapsula la tabella dei dati in ciascuna scheda:
Procedure Helicopters_OnClick
Set Proc to Heli.Wfm Additive
_app.aForms[NextNum] = New HeliForm() &&Crea un nuovo oggetto e memorizza l'indirizzo in un elemento di un array
Create Session &&Crea una nuova sessione
Do Heli.Qbe &&Apre la tabella richiesta
&&Nota: questo può anche essere fatto usando la proprietà view della scheda
_app.aForms[NextNum].Open() &&Apre la scheda.
Quando tutti i riferimenti alla tua scheda, sono rilasciati e rimossi,(non ci sono riferimenti oggetto), Visual dBase automaticamente chiude la Sessione.
Suggerimento: Non usare Create Session, quando non vuoi incapsulare i dati.
Se hai una scheda figlia di controllo
[lookup] dove vuoi che il puntatore al record
cambi anche nella scheda genitore, non hai
bisogno di incapsulare la scheda figlia.
In casi simili a questi, dove condividi
i dati tra oggetti, non usare Create
Session.
I Files .WFM, .CFM, .PRG e .CC
Normalmente le schede sono nei files .WFM, le procedure nei .PRG, le queries nei QBE, controlli custom nei .CC , le schede "Superclass" nei .CFM.
Nota bene che le tue classi, possono essere dovunque tu desideri. Esse non saranno eseguite.
Set Procedure To <C:\ MyDiskFile> è sufficiente per Visual dBase per trovare la tua classe - tramite il nome. Perciò, ogni file su disco che può essere caricato in memoria con "Set Procedure To" può contenere una definizione di classe.
Infatti ogni file caricabile può contenere diverse definizioni di classe !
Quando esegui "Do My.Wfm"
Local f &&questo codice viene eseguito
f = New MyForm()
f.Open()
CLASS MyForm of Form &&questo no!
...
...
ENDCLASS
Una definizione di classe, è solamente usata quando tu crei un'istanza - quando viene letto il codice "modello".
Perciò deve essere disponibile - in memoria - quando Visual dBase avrà necessità di leggerla, per creare un oggetto.
Un esempio di una chiamata "diretta" ad un oggetto:
Procedure LookupButton_OnClick
Set Procedure to C:\MyDir\My.WFM Additive
Form.oLookup = New MyForm()
Form.oLookup.ReadModal() (or oLookup.Open())
Form.oLookup.Release()
Close Proc C:\MyDir\My.Wfm
Schede Modali: Emulazione del comportamento di "ritorno" alla procedura chiamante
Ricorderai che abbiamo affermato più di una volta che "gli oggetti non sono sottoprogrammi e non restituiscono (return) il controllo a nessuno". Bene, c'è un caso speciale: Le Schede Modali.
Le schede possono essere "non modali" o "modali". Normalmente lo stato di una scheda è non modale.
Una scheda non modale ha le seguenti caratteristiche:
Mentre la scheda è aperta, il fuoco può essere
trasferito su altre schede. L'esecuzione
della routine che ha aperto la scheda continua
dopo che la scheda è stata aperta.
Le schede si aprono come finestre non modali
quando si vogliono aprire più schede contemporaneamente.
Ad esempio, un'applicazione che esegue numerose
attività può usare una scheda diversa per
ciascuna attività.
Schede Non Modali:
Procedure HeliLookup_OnClick
Set Proc to HeliLook.Wfm Additive
_app.oMyHelo = New HeliLookForm()
_app.oMyHelo.Open() &&Apertura non modale.
Form.Entryfield1.Value = 'Hello' && questa linea viene subito dopo l'apertura della scheda
Una scheda aperta come finestra modale ha
le seguenti caratteristiche:
Quando la scheda è aperta, il fuoco non può
essere trasferito su altre schede.
L'esecuzione della routine che ha aperto
la scheda si arresta finché la scheda non
viene chiusa. Quando la scheda non viene
chiusa, il controllo viene trasferito alla
riga di comando successiva a quella che ha
aperto la scheda.
Molte applicazioni usano le schede modali
come finestre di dialogo, che di regola chiedono
agli utenti di intraprendere un'azione prima
che la finestra di dialogo possa essere chiusa.
Schede Modali:
Procedure HeliLookup_OnClick
Set Proc to HeliLook.Wfm Additive
_app.oMyHelo = New HeliLookForm()
_app.oMyHelo.ReadModal() && Apertura modale .
Form.Entryfield1.Value = 'Hello' && alla chiusura di oMyHelo viene eseguita questa linea.
Le schede non modali sono aperte con il metodo Open(). Le schede Modali sono aperte con il metodo ReadModal().
Se hai bisogno di aprire una scheda, che faccia qualcosa e poi ritorni "indietro", usa ReadModal(). Non usare questa capacità delle schede modali per emulare codice procedurale per aggirare OO, prima o poi ti ritroverai "inscatolato"!!!
Ecco alcuni concetti rapidi per aiutarti a "Pensare OOP":
1. Creazione di Oggetti
A. File su disco caricato in memoria
B. Crea un nuovo Oggetto (Istanza)
C. Apri l'oggetto (nel caso di una scheda)
D. elimina l'oggetto
E. Scarica dalla memoria il file su disco.
2. Gli oggetti non "Ritornano" alle
procedure che li hanno creati, così imposta
le caratteristiche dell'oggetto prima che
sia "lanciato" oppure
incapsulale nell'oggetto stesso.
3. Le schede possono essere basate su altre
schede, i pulsanti (pushbuttons)
su altri pulsanti.
4. Le schede possono "parlare" con altre schede solo se possono trovare ciascuna altra variabili di riferimento all'istanza.
5. Gli eventi si attivano automaticamente
per capire quando si attivano aggiungi ?? CHR(7) ai possibili eventi.
?? CHR(7) è il campanello che ti avvertirà quando un evento si è verificato.
6. Prova a creare una nuova scheda base (.CFM) metti un oggetto rettangolo ed un bel oggetto testo colorato quale titolo. Usa l'opzione FILE del menu in Impostazione Scheda e scegli "Imposta classe scheda custom". Adesso puoi creare nuove schede basate sulla tua classe custom.
7. La cosa più importante: Non farti scoraggiare da OOP.
Può passare una settimana o un mese, ma uno giorno la "lampadina" si accenderà sulla tua testa e comincerai pensare o sognare in questo nuovo linguaggio, e ne sarà valsa la pena quando scoprirai quanto ti farà essere produttivo OOP!
9-1-1995