Function ClassCreate() Foundation
Creates a class dynamically (the class object).
ClassCreate( <cClassName> , ;
[<aSuperClass>] , ;
[<aMember>] , ;
[<aMethod>] ) --> oClassObject | NIL
Constant | Equivalent in the class declaration |
---|---|
CLASS_HIDDEN *) | HIDDEN: |
CLASS_PROTECTED | PROTECTED: |
CLASS_EXPORTED | EXPORTED: |
|
Constant | Equivalent in the class declaration |
---|---|
VAR_ASSIGN_HIDDEN | VAR <cName> ASSIGNMENT HIDDEN |
VAR_ASSIGN_PROTECTED | VAR <cName> ASSIGNMENT PROTECTED |
VAR_ASSIGN_EXPORTED | VAR <cName> ASSIGNMENT EXPORTED |
Constant | Equivalent in the class declaration |
---|---|
VAR_INSTANCE *) | VAR <cName> |
VAR_CLASS | CLASS VAR <cName> |
VAR_CLASS_SHARED | CLASS VAR <cName> SHARED |
|
Constant | Equivalent in the class declaration |
---|---|
CLASS_HIDDEN *) | HIDDEN: |
CLASS_PROTECTED | PROTECTED: |
CLASS_EXPORTED | EXPORTED: |
|
Constant | Equivalent in the class declaration |
---|---|
METHOD_INSTANCE *) | METHOD <cMethod> |
METHOD_CLASS | CLASS METHOD <cMethod> |
|
Constant | Equivalent in the class declaration |
---|---|
METHOD_ACCESS | ACCESS METHOD <cMethod> [VAR <cMember>] |
METHOD_ASSIGN | ASSIGN METHOD <cMethod> [VAR <cMember>] |
|
When a class is created, the function returns the corresponding class object. If the class <cClassName> exists already, NIL is returned.
The function ClassCreate() creates classes dynamically at runtime of a program. Dynamic classes have no class functions, they are represented only by class objects. A class function exists when classes are known at compile time. This applies to implicitly existing classes - like TBrowse() or XbpDialog() - as well as to those classes which are explicitly declared within CLASS..ENDCLASS statements.
Data for the definition of member variables and methods must be passed to ClassCreate() in the form of two dimensional arrays. The program code for methods is then represented by a code block whose first parameter is reserved. The first parameter receives the object (Self) when the method is called. If a method call includes additional parameters, they are passed on to the code block after Self (the first method parameter is the second code block parameter etc.)
When a class object is created, it remains in main memory regardless of whether or not it is referenced in a variable. It can be retrieved by the function ClassObject() at any time. This distinguishes a class object from its instances. Instances of a class are automatically removed from memory as soon as they are no longer referenced in a variable. A class object, however, must be removed explicitly by calling ClassDestroy() when the class is no longer needed in a program.
// The example implements the user-defined function DbRecord()
// which creates a class object for an open database. Objects
// of the class have instance variables whose names match with
// the field names of the database. The program code for the
// methods :init(), :get() and :put() is provided by code blocks
// which call STATIC functions. There, the instance variables
// of an object are accessed using the macro operator.
#include "Class.ch"
PROCEDURE Main
LOCAL oRecord
CLS
USE Customer
? Alias() // Result: CUSTOMER
? FIELD->LASTNAME // Result: Miller
oRecord := DbRecord():new()
? oRecord:className() // Result: CUSTOMER
? oRecord:lastname // Result: Miller
? oRecord:lastname := "Jones" // Result: Jones
? oRecord:put() // Result: .T.
? FIELD->LASTNAME // Result: Jones
? Recno() // Result: 1
oRecord:skip( 10 )
? Recno() // Result: 11
USE
RETURN
** Return class object for database in the current work area
** and create it if necessary.
FUNCTION DbRecord()
LOCAL aIVar, aMethod, oClass, nAttr, bSkip
oClass := ClassObject( Alias() )
IF oClass <> NIL
RETURN oClass // Class already exists
ENDIF
nAttr := CLASS_EXPORTED + VAR_INSTANCE
aIVar := AEval( DbStruct(), {|a| a:={a[1], nAttr} } ,,, .T.)
nAttr := CLASS_EXPORTED + METHOD_INSTANCE
aMethod := {{ "INIT" , nAttr, {|self| GetRecord(self) } }, ;
{ "GET" , nAttr, {|self| GetRecord(self) } }, ;
{ "PUT" , nAttr, {|self| PutRecord(self) } } }
// Method with parameter according to obj:skip( n )
bSkip := {|self,n| DbSkip(n), ::get() }
AAdd( aMethod, { "SKIP" , nAttr, bSkip } )
RETURN ClassCreate( Alias(),, aIVar, aMethod )
** Transfer values from fields to instance variables
STATIC FUNCTION GetRecord( oRecord )
AEval( DbStruct(), {|a,i| oRecord:&(a[1]) := FieldGet(i) } )
RETURN oRecord
** Transfer values from instance variables to fields
STATIC FUNCTION PutRecord( oRecord )
LOCAL lLocked := RLock()
IF lLocked
AEval( DbStruct(), {|a,i| FieldPut(i, oRecord:&(a[1])) } )
DbUnlock()
ENDIF
RETURN lLocked
If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use this form to report a documentation issue.