METODI INTERNI E VARIABILI ISTANZA:
-------------------------------------------------
Ogni classe creata con oObject contiene una quantità di IVars interne e metodi:
(1):: Dict Questo è un IVar che contiene l'oggetto _OBJECT_
che è stato usato creare la classe. E usato internamente per accedere all'oggetto ma contiene anche alcune informazioni
utili riguardo alla classe:
:: Dict:Name -> il nome della classe (come ::className())
:: Dict:ClsAlias -> la classe Alias
:: Dict:Handle -> la classe Handle (come ::ClassH())
:: Dict:NewObj -> una copia di self
:: Dict:Super -> l'istanza alla parent class
::Dict:bSuper -> il code block usato per creare l'istanza alla parent class
::Dict:Scope -> l'ultimo valore di valore di Scope
::Dict:nElem -> numero delle IVars di classe
::Dict:nMElem -> numero dei Metodi di classe
::Dict:Ivars -> Array delle Ivars di classe. Elementi:
{
IVar Name,
INLINE/BLOCK/STATIC Function,
Initial Value,
Scope, ;
Linked Method,
nPos,
Alias
}
:: Dict:Methods -> Array dei Metodi della classe. Elementi:
{
Method Name,
Method Function,
Method Alias,
Method Scope
}
(2)::Super La parent class se una è stato creata. Utilizzata anche per supportare ::<Alias>Super eredità Super Multipla, un IVar chiamato
::<ClassAlias>+"SUPER" è creato per ogni classe
Posto che che classe che DIALOG eredita da SCREEN-> BOX-> WINDOW possiamo inviare un messaggio direttamente alla classe BOX sovrascrivendo la parent class:
::Super:Display() -> calls WINDOW():Display()
(the immediate parent)
::BoxSuper:Display() -> calls BOX():Display()
(4)::__Super () Un METODO che può essere usato saltare a metodi della parent class, comunque è mezzo un po' più lento di quello descritto sopra.
Argomenti:
Il nome della classe super.
Posto che classe che DIALOG eredita da SCREEN-> BOX-> WINDOWpossiamo inviare un messaggio direttamente alla classe BOX
sovrascrivendo così la parent class:
::__super("BOX"):Display()
or the command ...
::super(BOX):display()
(5)::__virtual() Un METODO che ritorna solo self, usato per creare pezziper child methods in classi astratte. Per usarlo dichiara un metodo come VIRTUAL o DEFERRED. Non serve
referenziarlo altrimenti nel codice.
Non sarà ereditato in qualsiasi child class. Questo è tutto.
Nota: Un VIRTUAL METHOD sarebbe creato anche così:
.
METODO TestVirtual INLINE self
.
Questo approccio è davvero più veloce ma questo metodo
e sarà ereditato nella child class così com'è.
(6)::classInfo() Questo non può mancare. Tutti dovrebbero includerlonelle loro librerie, così perché no ...
Questa è un'utilità per ispezionare una classe.
Non potete alterare nulla nella classe, ma provvede a dare buone informazioni e si elimina all'uscita.
(7)::nMessage() Questo è usato per assegnare e richiamare valori di variabili istanza, direttamente usando self.
Il dizionario della classe è analizzato con il testo indicato
nel primo parametro. Se trovato, esso gli assegna un
nuovo valore a lui o ritorna il suo valore corrente:
self:nMessage (< [cMsg]>[,< [xValue]>])
E' necessario definire NO_DIRECT_IVARS con #define.
Vedi la sezione sotto "Modifica Diretta di Istance
Variables (settaggio veloce)" per una descrizione di un approccio più veloce. Questo metodo interno è solo incluso qui per completezza e dovrebbe essere scritto REALMENTE in C.
Comunque, quando si usa il codice per Classe (y) è
più facile compilare anche senza molti cambi.
(8)::InsData() Questo è il METODO più utile, in quanto permette di aggiungere IVars nuove, al volo, al runtime. Per
esempio si può aggiungere IVars per accedere a database DOPO l'inizializzazione della classe.
Verificate di non terminare lo spazio per le IVar. Se questo
accade, modificate quale funzione IVar nel bsg.prg.
o:InsData (<cIVarName>,[<bBlock>],[<xData>])
Argomenti:
<cIVarName> è il nome (messaggio) dell'IVar
<bBlock> è un code block opzionare (come DATa ... BLOCK).
<cData> è valore opzionale dell'IVar, non usato se<bBlock>
è usato.
// Questo esempio mostra come compi di un database possono essere inseriti
// a runtime. Si veda oDBTest1.prg ed oDBTest2.prg per due __differenti__
// approcci allo stesso problema.
CLASS dBServer ALIAS dBS
DATA aBuffer AS ARRAY // deve essere #1
DATA Alias AS ""
...
...
METHOD AddFlds = _AddFlds // Inizializza il campo IVars
METHOD Read = dbsRead // Legge il record in ::aBuffer
METHOD Write = dbsWrite // Writes record from ::aBuffer
...
...
ENDCLASS
...
...
METHOD FUNCTION dbsWrite()
AEval( ::Buffer, { | u, n | (::cAlias)->(FieldPut( n, u )) } )
(::cAlias)->(DbSkip(0))
(::cAlias)->(dbCommit())
RETURN self
METHOD FUNCTION dbsRead()
Local i
FOR i=1 TO LEN( ::Buffer )
::Buffer[ i ] := (::cAlias)->(FieldGet( i ))
NEXT
RETURN self
METHOD FUNCTION _AddFlds()
// Dopo che il database è aperto e pronto all'utilizzo
FOR i=1 TO (::alias)->(FCOUNT())
// get set block per ::aBuffer array
::InsData( Field( i ), &( "{ | Self, xVal | if( xVal == NIL, Self[ 1 ][" +;
Str( i ) + "], Self[ 1 ][" + Str( i ) + "] := xVal ) }" ) )
NEXT
RETURN self
MODIFICA DIRETTA DI ISTANCE VARIABLES (settaggio veloce):
-------------------------------------------------------------------------
Settaggio veloce di IVars non è ancora perfezionato. Comunque c'è un facile
modo di farlo senza alcuna biblioteca di classe che non cambia l'ordine nel quale IVars è stato dichiarato durante creazione della classe.
Quello che fa è che direttamente cambia lo stesso elemento dell'ordine che l'Ivar occupa. Questo è molto più veloce del solito modo in cui IVar indirizza (::) ed è anche il solo modo per alterare il valore di un READONLY IVar, [e.g].
#xTranslate @:Color => self\[\1] // Il modo usato da Class(y)
CLASS window ALIAS win
DATA Color // Dichiara ::Color per primo come Self[1]
...
ENDCLASS
...
...
@:Color := "N/W"
@:Color := "R/W"
Comunque questo è solo valido nella classe attuale esso e NON in qualsiasi
inherited class (eccetto se usate ::super(SUPERCLASS):IVar)
Un altro caso per usare questa sintassi è fra User Defined IVar Functions.
In questi casi non può usare il :: operatore che avrebbe come conseguenza un
errore interno (processor stack fault) e sette anni di cattiva fortuna)