This is an expanded version of Steve Klingler's pseudo object
definitions.

It implements Nantucket's style Instance variables as well as
Methods.  The only difference resides in the syntax: the "()" must be
used even though it is a "variable".


How to implement;

CLASS DEFINITION ".ch"

EXPORT METHOD      class:exported_method  num1, num2
<repeat for all exported methods>

EXPORT NON_ASSIGN  class:non assignable instance var  num1, num2
<repeat for all non assignable instance variables>

EXPORT ASSIGNABLE  class:assignable instance var    num1, num2


CLASS DEFINITION FUNCTION

Rather than a #define  Class array, I use a Static Multiple Level 
array variable  where 
FUNCTION pseudoclass( num1, num2 )

  STATIC saPseudoClass := {  
                            {  code blocks array for EXPORTED METHODS },
                            {  code blocks array for EXPORT NON-ASSIGN },
                            {  code blocks array for EXPORT ASSIGNABLE }
                           }
RETURN ( saPseudoClass[ num1, num2 ] )

Easier to use with CLD.EXE !



and of course, @ la Nantucket a pseudo object creation function 
( GetNEW, TBrowseNEW... )


FUNCTION PseudoClassNEW( your optional parameter list for object init values )
STATIC saPseudoObj:={}  //  defined once
LOCAL aInstance 

IF saPseudoObj is an empty array
  ASIZE it
ENDIF

aInstance := ACLONE( saPSeudoObj )

ASSIGN all the required value passed as parameters

RETURN ( aInstance )



These functions ( "Class Def" and "Instance New" ) are the only visible 
( NON STATIC ) functions in your module.


Examples:
Exported methods 
  Nantucket uses in the Clipper 5.0 implementation the following
  notation.

  Class:Exported Method() -> self

  The Pseudo-Object being an array, it is passed by reference. 
  Hence the following construction is used throughout:

  Static Function ExportedMethod1( poAny, < parameter list > )
    .... any code that manipulates the object
  Return ( poAny )

Outside the PseudoClass .PRG we then can code:

   ClassInstance:ExportedMethod1( <parameter list> )

   .PPO transalation
   ClassInstance:= EVAL( Class( num1, num2 ), ClassInstance,<list> )
    


Non-Assignable can be queried only as their value is determined
within the instance of the class.
 Reference Get Class : badDate, decPos, hasFocus in Nantucket
 Documentation.
 
 Static Function Non-Assign1( poAny )
 Return( poAny[ Choosen Non- Assignable Array Element ] ) 

Outside the PseudoClass .PRG we then can code:

   IF ClassInstance:Non-Assign1()              //  for Valtype = 'L'
     ...
   ENDIF


   .PPO translation
   IF ! EVAL( Class( num1, num2 ), ClassInstance )
     ...
   ENDIF
   

Assignable can be either queried or filled in.  Suggestion is the do
some type checking on the passed parameter.
  Reference TBrowse Class ColPos ColSep goTopBlock etc...

  Static Function Assignable1( poAny, p_xany )
  Return( IIF( p_xany != nil .and. valtype( p_xany ) = "OK  type",;
               poAny[ Choosen Assignable ] := p_xany,             ;
               poAny[ Choosen Assignable ]                        ;
        )
                            


Outside the PseudoClass .PRG we then can code:

   anyvar := ClassInstance:Assignable1()
   
   .PPO translation
   anyvar := EVAL( Class( num1, num2 ), ClassInstance )
   
   and

   ClassInstance:Assignable() := anyvar
   
   .PPO translation
   EVAL( Class( num1, num2 ), ClassInstance, anyvar ) 

Oddly enough by using this implementation we find that Exported
methods have a taste of "procedure" as opposed to Exported Instance
Variables which have a taste of "function". Let's keep notation
simple!


RICHARD LALONDE 70012,535  23/06/91





