First Class - Have Questions

I’ve never really need to build my own class. But this new project gave me the opportunity to at least try it.

I need to build a class that includes StringTheory, jFiles & libCurl. I have been using StringTheory/jFiles as a template to build the basic structure. Overall it has worked out with the following (so far) problems that I cannot resolve.

  1. In my clw file, if I include the keyword MEMBER I get 2 compile errors, Invalid MEMBER statement and Expected:;INCLUDE OMIT SECTION COMPILE PRAGMA GROUP ITEMIZE MAP If I comment out MEMBER, it gets past it. Every class I’ve seen has MEMBER!
  2. Procedure doesn’t belong to module MEDICICLASS.Destruct. I get this error message for all declared Methods!

Any suggestions are welcome.

Thanks.

Take a look at CapeSoft’s solution, makes class inclusion simple. Check for Cape01.tpw / Cape02.tpw under C:\Clarion\v11\accessory\template and follow the instructions. I think they are automatically includes with all his products by defaults. Not sure is webinar on them or not.

I think you’re pretty close. You definitely need the MEMBER statement. The INCLUDE(‘YourClassInc.inc’) needs to match the actual filename of your class file.

I would recommend naming your class files with the word Class at the end, and ensuring that your stuff inside the INC file cannot clash with other variable names in your app. Also, not sure what you’re expecting to happen with that global “Docs” queue (non TYPE).

This is why most of your errors were happening

As stated previously, I think you should name your files that way anyway.

As @jslarve said you definitely do need a member statement.

Your CLW has an include to MediciClass.inc and that I guess you meant Medici.inc.

I think you are going to start to find a lot of errors after the class compiles though as in the CLW file it looks like you are referencing program data, for instance

CIS:CountyName = self.Get_CountyName(CIS:CountyName)

If that was your intention then you will need to change the MEMBER to become part of the exe.

   MEMBER('MyExeName.clw')

You should note though that then you class becomes limited to the exe it is tied to.

I hope this helps a little, and good luck in getting it working.

Mark

I make a new Class from one file that has both INC and CLW so in the one file I can do a search and replace.

  1. Starting with a template “.Inc.Clw” file
  2. Search and Replace the Tokens like ClassFile ClassName Queue_TYPE QueueName
  3. Save the separate .INC and .CLW files

Here’s one from the below link that dose a Class with a QUEUE. I split into 2 parts. The idea is to put in most anything you might need because it is easy to delete. Like this has methods to Add/Delete/Free Q that I probably will not use.

Carl's Class Template to make a Class with a Queue:                    _Class_Make_Queue_v5.inc.clw

    Find and Replace tokens _{Token}_ like _ClassFile_   _ClassName_
    Find and Replace tokens for Queue like _Queue_TYPE_  _QueueName_
    Find and Replace __Proc_# with the Procedure Name you prefer. Add any addional.
    Save this as 2 files an .INC and .CLW

!Region Class Description -----------------------------------------------------
! _ClassFile_ by Carl Barnes created on // for
!
! This Class description
!------------------------------------------------------------------------------
 OMIT('**How to Implement**')                 ! How to Implement this Class:
   INCLUDE('_ClassFile_.INC'),ONCE            !  1. Global Includes:
_ClassName__Cls  _ClassName_                  !  2. Procedure Data: Declare Class Instance
_ClassName__Cls  CLASS(_ClassName_) ; END     !                  or Derive Class
    _ClassName__Cls.Init( )                   !  3. Procedure Code: Init the Class 
!End Omit -- **How to Implement** ---------------------------------------------
!------------------------------------------------------------------------------
! Change History
!   -  -    Original
!
!EndRegion Class Description --------------------------------------------------

__ClassFile__Present_  EQUATE(1)      ! OMIT('_EndOfInclude_',__ClassFile__Present_)   ! _EndOfInclude_

_Queue_TYPE_ QUEUE,TYPE
__Q_Field_1        LONG
__Q_Field_2        STRING(40)
               END


!----------------- _ClassName_ -----------------
_ClassName_    CLASS,TYPE,MODULE('_ClassFile_.CLW'),LINK('_ClassFile_.CLW',1),DLL(0)   !,_ABCLinkMode_),DLL(_ABCDllMode_)  !ABCIncludeFile
!
!Properties
!-----------------------
_QueueName_             &_Queue_TYPE_    !,PROTECTED

!Methods
!-----------------------
Init                    PROCEDURE(),VIRTUAL
Kill                    PROCEDURE(),VIRTUAL
_QueueName__AddQ        PROCEDURE(),VIRTUAL !,PROTECTED
_QueueName__FreeQ       PROCEDURE(),VIRTUAL !,PROTECTED
_QueueName__DeleteQ     PROCEDURE(),VIRTUAL !,PROTECTED
__Proc_1                PROCEDURE(),VIRTUAL
__Proc_2                PROCEDURE(),VIRTUAL
__Proc_3                PROCEDURE(),VIRTUAL
__Proc_4                PROCEDURE(),VIRTUAL
__Proc_5                PROCEDURE(),VIRTUAL

!Properties Internal
!-----------------------

!Methods Internal
!-----------------------
CONSTRUCT               PROCEDURE()
DESTRUCT                PROCEDURE(),VIRTUAL
__Internal_Method_1     PROCEDURE(),VIRTUAL,PRIVATE
                    END

    ! _EndOfInclude_

End Of .INC #################### _ClassFile_.INC ####################  Save ABOVE as _ClassFile_.INC

Begin  .CLW #################### _ClassFile_.CLW ####################  Save BELOW as _ClassFile_.CLW

                    MEMBER()
!------------------------------------------------------------------------------
! _ClassName_ by Carl Barnes created on // for
!
!------------------------------------------------------------------------------
!Region -- Change Notes -------------------------------------------------------
! Date and Change Description
!   -  -    Original
!
!EndRegion -- Change Notes ----------------------------------------------------

    INCLUDE('_ClassFile_.INC'),ONCE
!   INCLUDE('KEYCODES.CLW'),ONCE  INCLUDE('CWSYNCHM.INC'),ONCE  INCLUDE('CWSYNCHC.INC'),ONCE

    MAP
DB     PROCEDURE(STRING DebugMsg),PRIVATE
       MODULE('WinAPI')
OutputDebugString   PROCEDURE(*CSTRING cMsg),PASCAL,DLL(1),RAW,NAME('OutputDebugStringA')
       END

!-- _ClassName_ - Private Class Methods in Clw Map --
__Private_Map_1  PROCEDURE(_ClassName_ SELF),PRIVATE
    END

!--------------------------------------
_ClassName_.CONSTRUCT   PROCEDURE()
!--------------------------------------
    CODE
    IF (SELF._QueueName_ &= NULL) THEN
       SELF._QueueName_ &= NEW _Queue_TYPE_
    END
    RETURN
!--------------------------------------
_ClassName_.DESTRUCT   PROCEDURE()
!--------------------------------------
    CODE
    IF NOT (SELF._QueueName_ &= NULL)  THEN
       SELF._QueueName__FreeQ()    !FREE(SELF._QueueName_)
       DISPOSE(SELF._QueueName_)
    END
    RETURN

!--------------------------------------
_ClassName_.Init   PROCEDURE()
!--------------------------------------
    CODE
    MESSAGE('_ClassName_.Init() ||For Queue SELF._QueueName_ |of Type _Queue_TYPE_' ,'_ClassName_.Init()')
    RETURN
!--------------------------------------
_ClassName_.Kill   PROCEDURE()
!--------------------------------------
    CODE
    RETURN

!======================================== Procedures to manage _QueueName_ QUEUE of TYPE  _Queue_TYPE_
!--------------------------------------
_ClassName_._QueueName__AddQ   PROCEDURE()
!--------------------------------------
  CODE
  CLEAR(SELF._QueueName_)
  !SELF._QueueName_.__ANY_Field_1   = Param
  !SELF._QueueName_.__ANY_Field_2  &= Param
  !SELF._QueueName_.__Ref_Field_3  &= New()
  ADD(SELF._QueueName_) ! , SELF._QueueName_. , SELF._QueueName_. )
  RETURN

!--------------------------------------
_ClassName_._QueueName__FreeQ   PROCEDURE()
!--------------------------------------
Ndx LONG,AUTO
  CODE
  IF SELF._QueueName_ &= NULL THEN RETURN.
  DB('_ClassName_._QueueName__FreeQ Records='& RECORDS(SELF._QueueName_))
  LOOP Ndx=RECORDS(SELF._QueueName_) TO 1 BY -1
    GET(SELF._QueueName_, Ndx)
    IF ERRORCODE() THEN BREAK.
    SELF._QueueName__DeleteQ()
  END
  FREE(SELF._QueueName_)
  RETURN

!--------------------------------------
_ClassName_._QueueName__DeleteQ   PROCEDURE()
!--------------------------------------
  CODE
  !DISPOSE of New &References in this Q. Set ANY &=  NULL
  !SELF._QueueName_.__AnyField_1  &= NULL
  !SELF._QueueName_.__AnyField_2  &= NULL
  !DISPOSE(SELF._QueueName_.__RefField_3)  !Dispopse of &= New()
  !CLEAR(SELF._QueueName_)
  DELETE(SELF._QueueName_)
  RETURN

!--------------------------------------
_ClassName_.__Proc_1   PROCEDURE()
!--------------------------------------
    CODE
    MESSAGE('_ClassName_.__Proc_1() ' & |
            '||Records in _ClassName_ Queue _QueueName_ ='&RECORDS(SELF._QueueName_) ,'_ClassName_.__Proc_1()')
    RETURN
!--------------------------------------
_ClassName_.__Proc_2   PROCEDURE()
!--------------------------------------
    CODE
    RETURN
!--------------------------------------
_ClassName_.__Proc_3   PROCEDURE()
!--------------------------------------
    CODE
    RETURN
!--------------------------------------
_ClassName_.__Proc_4   PROCEDURE()
!--------------------------------------
    CODE
    RETURN
!--------------------------------------
_ClassName_.__Proc_5   PROCEDURE()
!--------------------------------------
    CODE
    RETURN

!========================================================== PRIVATE Methods === 
!-------------------------------------------
_ClassName_.__Internal_Method_1  PROCEDURE() !PRIVATE
!-------------------------------------------
    CODE
    RETURN
!----------------------------------------
_ClassName_.__Private_Map_1   PROCEDURE() !PRIVATE      Not in INC in CLW MAP as PROCEDURE(_ClassName_ SELF),PRIVATE
!----------------------------------------
    CODE
    RETURN

!--------------------------------------
DB          PROCEDURE(STRING DebugMsg)
Prfx EQUATE('_ClassFile_: ')
cDbg CSTRING(SIZE(Prfx)+SIZE(DebugMsg)+3),AUTO
  CODE
  cDbg=Prfx & CLIP(DebugMsg) & '<13,10>'
  OutputDebugString(cDbg)
  RETURN

Class templates are on GitHub in this GIST

1 Like

Sorry for the delayed response. Got pulled onto another issue.

Thank you for your suggestions and help. After implementing your suggestions, I was able to get the class to work after realizing it is more of a local class than a global class. Thus it did not need the Module or Link modifiers on the Class definition. Once I got the Project defines corrected, it all worked out.