PROBLEMI dell'EREDITARIETA':
-------------------------------------


In oObject il tipo ::super:<method> di ereditarietà non è usato realmente. Invece oObject utilizza una tecnica denominata "method aliasing". Questa tecnica richiede che ogni nuova classe abbia un suo proprio "alias", uno pseudonimo che oObject usa internamente per rinominare i parent methods e trasferirli nelle classi child. Ad esempio:
(1) CLASS Parent Alias oP
...
METHOD Display()
...
ENDCLASS

(2) CLASS Child ALIAS oC
...
METHOD Display()
...
ENDCLASS

In questo esempio classe "Child" ha 2 metodi ::diplay(), il suo proprio ::display() e suo metodo genitore ::oPDisplay().Parent Methods che non condividono lo stesso nome come classe child sono trasferiti senza alias.

Questa tecnica assicura che ciascuna nuova classe è contenuta di per se e non fa realmente riferimento alla Parent Class eccetto che al momento della sua creazione. Altre biblioteche OOP mantengono array statici che sono analizzati per trovare il corretto parent:method. Questo non è necessario in oObject poiché ciascuna classe contiene tutti metodi di cui puo aver bisogno - eccetto i METHODS/IVARS interni e locali.

Questo comunque genera un altro problema. Classi che prevedono un numero enorme di messaggi. Object supporta fino a 250 Istance Variables e INLINE-BLOCK. Statements e illimitati PUBLIC METHODS (STATIC METHODS sono implementati con INLINE statements) ma sta a VOI mantenere le Vostre classi piccole e veloci. Utilizzate un oggetto subclassing (l'IVar di un oggetto è un riferimento a un altro oggetto) per evitare un'ereditarietà non necessaria.

Per compatibilità ciascuna classe porta un riferimento al suo genitore nel ::DICT:Super IVar ed nel ::Super IVar. Accedere a Parent Classes utilizzando ::Super:<Messagge> è più lento che utilizare direttamente l'ALIASed
Parent Method.

Inoltre, accedere a ::super utilizzando ::Super:<Message> è necessario per inizializzazare tutte l'IVars prima che si renda necessario utilizzare il ::Super:<Message>, vale a dire i suoi parametri formali, poiché la parent class non è stata propriamente inizializzata nella child class. (vedi "TestSta* .prg" nella directory EXAMPLES).

A partire dalla versione 2.Ab oObject supporta anche la vera ereditarietà delle classi native di Clipper (non subclassing). L'utilizzo di questa caratteristica si verifica anche in classi con troppi messaggi.

Nota: la realizzazione di questa tecnica nella versione 2.B assicura che i Metodi delle classi native sono ereditati come veri PUBLIC Methods e IVars come IVars (vedi ooBject.prg - METHOD __SuperMethod() ).


ASSEGNAZIONE DELLE VARIABILI:
------------------------------------------


Potete immagazzinare valori di default per istanziare variabili al momento della inizializzazione della nuova classe; cioè fra gli statements CLASS <cClass> ... e ENDCLASS al momento della dichiarazione delle nuove variabili, ad esempio:

VAR test1 AS INT // test1 is 0
VAR test2 AS FLOAT // test2 is .F.
VAR test3 AS DATE // test3 is CTOD(" / / ")
VAR test4 AS TBrowseDB() // test4 is TBrowse object
...etc...
ENDCLASS


Per alcuni tipi di variabili, questo è molto importante poiché si può (a) risparmiare molte linee del codice di inizializzazione del Vostro CONSTRUCTOR method e (b) READONLY variabili che devono essere ereditated da altre classi devono avere un valore all'inizializzazione della classe.

Notate comunqueche in alcuni casi questa caratteristica non è solo non desiderata ma può produrre anche alcuni risultati erronei, ad esempio un contatore che è incrementato nel primo esempio della classe e mantiene il suo valore nell'esempio successivo, assomiglia al comportamento di una variabile STATIC.

Questo naturalemente avviene se la Vostra funzione INIT/Constructor non assegna valori alle variabili della classe.

Sta a Voi decidere quale IVars inizializzare nella funzione costruttore e quali no.

Specialmente per le variabili READONLY, possono essere assegnati valori nuovi solo all'interno delle loro classi e solo in due modi:

a) Assegna un valore alla dichiarazione della classe, tra i comandi CREATE CLASS e ENDCLASS 

b) Assegna un valore utilizzando l'operatore @:, per modificare direttamente l'elemento che punta alla variabile (vedi "Modifica Diretta di
Variabili istanza - modifica veloce" ).


USER DEFINED GET/SET IVARS
~~~~~~~~~~~~~~~~~~~~~~~~~

Ogni istance variable è infatti assegnata e recuperata usando una GET / SET Function o una combinazione di GET/SET Functions.

Per usare questa caratteristica che deve far riferimento direttamente Self ELEMENT che volete utilizzare all'interno della vostra GET/SET function. Questo vuole dire non potete usare l'operatore send (::) per assegnare o recuperare manualmente il valore dell'IVar. Questo avrebbe come conseguenza un errore di recursione del "processor stack"

Potete ovviamente referirVi ad altre class IVars utilizzando l'operatore send.
Per esempio:
#translate GETSET( <xVal>, <xParm> ) => ;
<xVal> := IF( xVal==NIL, <xVal>, <xVal> := <xParm>)

CLASS Test
DATA Mydata1 GETSET My1SpecialFunc // No 1 self element
DATA Mydata2 GETSET My2SpecialFunc // No 2 self element
...
ENDCLASS

FUNCTION My1SpecialFunc( xVal )
IF xVal == NIL
RETURN QSelf[1]
ELSE
QSelf()[1] := SomeFunc( xVal )
ENDIF
RETURN QSelf()[1]

FUNCTION My2SpecialFunc( xVal )
RETURN GETSET( QSelf()[2], xVal )



                                                                                                                           

Hosted by www.Geocities.ws

1