Page 1 of 1

OOP with macros and functions from an include file

Posted: Sat Mar 18, 2006 9:39 pm
by helpy
Hi to all,

I wrote an include file (Download: ClassTools.pbi) with some macros and functions, which you could use to do the following:

Code: Select all

XIncludeFile "ClassTools.pbi"

;=======================================================
; Define the Class (Interface) of FIRST_CLASS
DEFINE_CLASS(FIRST_CLASS)
  SetName(Name.s)
  GetName.s()
  Release()
END_CLASS(FIRST_CLASS)


; Define Class data
DEFINE_CLASS_DATA(FIRST_CLASS)
  Name.s
END_CLASS_DATA

; Class Methods
METHOD_1(FIRST_CLASS,SetName,l,Name.s)
  CLASS_DATA\Name = Name
END_METHOD

METHOD_0(FIRST_CLASS,GetName,s)
  METHOD_RETURN(CLASS_DATA\Name)
END_METHOD

METHOD_0(FIRST_CLASS,Release,l)
  METHOD_RETURN(CLASS_RELEASE)
END_METHOD


; CLASS Constructor
CLASS_CONSTRUCTOR(FIRST_CLASS)
  VTABLE(FIRST_CLASS,SetName)
  VTABLE(FIRST_CLASS,GetName)
  VTABLE(FIRST_CLASS,Release)

  CONSTRUCTOR_INIT(FIRST_CLASS)
  CLASS_DATA\Name = "Initial Name"
END_CONSTRUCTOR(FIRST_CLASS)
;=======================================================

;Test FIRST_CLASS
Debug "--------------------------------"
Debug "Test of FIRST_CLASS"
Debug "--------------------------------"
oClass.IClass(FIRST_CLASS) = NEW_OBJECT(FIRST_CLASS)
Debug oClass\GetName()
oClass\SetName("New Name")
Debug oClass\GetName()
Debug oClass\Release()     ; returns #True if successful


;=======================================================
; Define the Class (Interface) of SECOND_CLASS
DEFINE_CLASS(SECOND_CLASS) Extends EXTEND_CLASS(FIRST_CLASS)  
                           ; need the Extends keyword becaus of a macro bug!
                           ; otherwise the Extends keyword would be in ClassTools.pbi
  SetCountry(Country.s)
  GetCountry.s()
END_CLASS(SECOND_CLASS)


; Define Class data
DEFINE_CLASS_DATA(SECOND_CLASS) Extends EXTEND_CLASS_DATA(FIRST_CLASS)
                                ; need the Extends keyword becaus of a macro bug!
                                ; otherwise the Extends keyword would be in ClassTools.pbi
  Country.s
END_CLASS_DATA

; Class Methods
METHOD_1(SECOND_CLASS,SetCountry,l,Country.s)
  CLASS_DATA\Country = Country
END_METHOD

METHOD_0(SECOND_CLASS,GetCountry,s)
  METHOD_RETURN(CLASS_DATA\Country)
END_METHOD

METHOD_0(SECOND_CLASS,Release,l)
  METHOD_RETURN(CLASS_RELEASE)
END_METHOD


; CLASS Constructor
CLASS_CONSTRUCTOR(SECOND_CLASS,FIRST_CLASS) ; Second class name is the one
                                            ; which should be extended
  VTABLE(SECOND_CLASS,SetCountry)
  VTABLE(SECOND_CLASS,GetCountry)
  VTABLE(SECOND_CLASS,Release)              ; Replace the Release() function of 
                                            ; FIRST_CLASS With new one
  CONSTRUCTOR_INIT(SECOND_CLASS)
  CLASS_DATA\Country = "Initial Country"
END_CONSTRUCTOR(SECOND_CLASS)
;=======================================================

;Test SECOND_CLASS
Debug "--------------------------------"
Debug "Test of SECOND_CLASS"
Debug "--------------------------------"
oClass2.IClass(SECOND_CLASS) = NEW_OBJECT(SECOND_CLASS)
Debug oClass2\GetName()
Debug oClass2\GetCountry()
oClass2\SetName("New Name")
oClass2\SetCountry("New Country")
Debug oClass2\GetName()
Debug oClass2\GetCountry()
Debug oClass2\Release()    ; returns #True if successful


;=======================================================
; Debuger output:

; --------------------------------
; Test of FIRST_CLASS
; --------------------------------
; Initial Name
; New Name
; 1
; --------------------------------
; Test of SECOND_CLASS
; --------------------------------
; Initial Name
; Initial Country
; New Name
; New Country
; 1
The macros and functions in ClassTools.pbi are based on
Danilos OOP concept which you can find in his examples:

=> Danilos OOP examples

Some remarks:
  • Two macros in one line ...
    If this is changed I could simplify it like mentionend in the comments of the example.
  • FreeStructureStrings as normal PB FUNCTION/COMMAND
    Because of this memory leak the release of objects does not free the strings in the example.
  • Macro with wildcard for arguments
    With with feature I could simplify a lot more. Now I need the macros METHOD_0, METHOD_1, METHOD_2, ... for methods with 0, 1, 2 ore more arguments.
    The actual include file only supports NEW_OBJECT(ClassName) without inital parameters. This could also be very easy with "wildcard argument".
What do you say? How does it look like?
Do have some suggestions for improvements?

cu, helpy

[edit]
added download link at top of this posting.
[/edit]

Posted: Sat Mar 18, 2006 10:41 pm
by helpy
And here the include file: ClassTools.pbi

Posted: Sun Mar 19, 2006 10:54 am
by remi_meier
Actually for me, it seems even more unreadable and some of the macros
are just wrappers for keywords. Furthermore there is a confusion with the
word define and declare :wink: . We don't even save much typing with
these macros.

The good thing is, that the names of the "keywords" are more OOP like
and so we don't have to mix interfaces with structures but just have
classes.

Perhaps it's just not my style :P

greetz
Remi

Posted: Sun Mar 19, 2006 8:15 pm
by helpy
remi_meier wrote:Actually for me, it seems even more unreadable
Thats right! This needs getting used to!
For me it is great help, because it is less typing!
remi_meier wrote:... and some of the macros are just wrappers for keywords.
Yes! That is right! I did this, because for me the readability is greater, when a block, which starts with METHOD_X also ends with END_METHOD.

And the second reason is, that in future I can also add standard code for cleaning up a method.
remi_meier wrote:Furthermore there is a confusion with the
word define and declare :wink: .
This I do not understand! Maybe because my native language is not english! I just used the macro names DEFINE_CLASS and DEFINE_CLASS_DATA, which also can easily be changed.
remi_meier wrote:We don't even save much typing with
these macros.
Not with the ones which are just wrappers for one keyword.

But I also have the idea to implement some checks, which will avoid double naming of classes or methods. There would be a compiler warning with an appropriate message ... this check would not produce additional overhead to the code ...

cu, helpy