INTERNAL METHODS AND INSTANCE VARIABLES:
----------------------------------------
Every class created with oObject contains a number of internal IVars and methods :


(1) ::Dict This is an IVar that contains the _OBJECT_ object  that was used to create the class. It is used
internally to access the object but also contains some useful info regarding the class:

::Dict:Name -> the class Name (like ::className())
::Dict:ClsAlias -> the class Alias
::Dict:Handle -> the class Handle (like ::ClassH())
::Dict:NewObj -> a copy of self
::Dict:Super -> the parent class instance
::Dict:bSuper -> the code block used to create the parent class instance
::Dict:Scope -> Last value of Scope
::Dict:nElem -> Total IVars of class
::Dict:nMElem -> Total Methods of class
::Dict:IVars -> Array of class IVars. Elements:
{
IVar Name,
INLINE/BLOCK/STATIC Function,
Initial Value,
Scope, ;
Linked Method,
nPos,
Alias
}

::Dict:Methods -> Array of class Methods. Elements:
{
Method Name,
Method Function,
Method Alias,
Method Scope
}


(2) ::Super The immediate parent class if any was used. Also to support ::<Alias>Super Multiple inheritance, an IVar called ::<ClassAlias>+"SUPER" is created for every class up the foodchain.

Supposing class DIALOG inherits from SCREEN->BOX->WINDOW we may send a message directly to the BOX class thus overriding the immediate parent class:

::Super:Display() -> calls WINDOW():Display()
(the immediate parent)

::BoxSuper:Display() -> calls BOX():Display()


(4) ::__Super() A METHOD that can be used to jump to parent classes methods, however it is a bit slower than the alternative ways to do that described above.

Arguments:

The name of the super class.

Supposing class DIALOG inherits from SCREEN->BOX->WINDOW we may send a message directly to the BOX class thus overriding the immediate parent class:

::__super("BOX"):Display()

or the command ...

::super(BOX):display()

(5) ::__virtual() A METHOD that only returns self, used to create slots for child methods in abstract classes. To use it just declare a method as VIRTUAL or DEFERRED. You don't have to reference it anywhere else in your source code. It will not be inherited in any child classes. That is your job ;)

Note: A virtual METHOD would also be created this way:

...
METHOD TestVirtual INLINE self
...

This approach is actually faster but this method will be inherited in child classes as is...

(6) ::classInfo() This couldn't be missing <g>. Everybody seems to be including one of these in their libraries, so why not... This is a class inspection utility. You can not alter anything in the class so far but it provides good info and cleans up after itself.

(7) ::nMessage() This is used for assignment and retrieval of values to class instance variables, directly using self. The class dictionary is scanned for the text described in the first parameter. If found, it either assigns a
new value to it or returns its current value:

self:nMessage( <cMsg> [, <xValue>] )

You must #define NO_DIRECT_IVARS to use this approach. See the section below "Direct modification of Instance Variables (early binding)" for a description of a much faster approach. This internal method is only included  here for completion and should REALLY be written in C. However, when using code written for Class(y) it makes it easier to compile without too many changes.


(8) ::InsData() This is the most useful internal METHOD so far. It is used to add new IVars, on the fly, at runtime. For example you can add IVars to access database fields AFTER class initialization e.g.

(Be careful not to run out of IVar functions. If this happens, add some IVar functions to bsg.prg)

o:InsData( <cIVarName>, [<bBlock>], [<xData>] )

Arguments :

<cIVarName> is the name (message) of the IVar

<bBlock> is an optional code block (same as DATA ... BLOCK)

<cData> is optional value of the IVar, not used if <bBlock>
is used.


// This example shows how database field variables can be inserted 

// at runtime. Read oDBTest1.prg and oDBTest2.prg for two __different__ 

// approaches to the same problem.

CLASS dBServer ALIAS dBS
DATA aBuffer AS ARRAY // MUST be #1
DATA Alias AS ""
...
...
METHOD AddFlds = _AddFlds // Initializes field IVars
METHOD Read = dbsRead // Reads record into ::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()
// After you you have the database open and ready
FOR i=1 TO (::alias)->(FCOUNT())
// get set block for ::aBuffer array
::InsData( Field( i ), &( "{ | Self, xVal | if( xVal == NIL, Self[ 1 ][" +;
Str( i ) + "], Self[ 1 ][" + Str( i ) + "] := xVal ) }" ) )
NEXT
RETURN self


DIRECT MODIFICATION OF INSTANCE VARIABLES (Early Binding):
----------------------------------------------------------
Early binding of IVars is not yet implemented. However there is an easy way to do it with any class library that does not modify the order in which IVars were declared during class creation.

What you do is you directly modify the self array element that the IVar occupies. This is much faster than the usual way of IVar addressing (::) and it is also the only way to alter the value of a READONLY IVar, e.g.

#xTranslate @:Color => self\[\1] // The Class(y) way

CLASS window ALIAS win
DATA Color // Declare ::Color FIRST as Self[1]
...
ENDCLASS
...
...
@:Color := "N/W"
@:Color := "R/W"

However this is only valid in the actual class itself and NOT in ANY inherited classes ( except if you use ::super(SUPERCLASS):IVar )

Another case to use this syntax is from within User Defined IVar Functions. In these cases you CAN NOT use the :: operator as it would result in an internal error (processor stack fault) and seven years of bad luck :-)

( see also LINKed IVars below and take a look at ClipOO.ngt in the
HELP directory )



                                                                                                                           

Hosted by www.Geocities.ws

1