~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LCP - Little Class preprocessor
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
OOP preprocessor - by FSW - Version 0.7 - August 2006
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This software is called Little Class Preprocessor because it is a little class
preprocessor.
It is not the intention of this piece of software to turn PureBasic into a full blown
OOP language.
If you need a full blown OOP language use C++/Eiffel/Java etc.
You can already create Objects with PureBasic with the help of Structures/Interfaces.
The intention of this software is to make the creation of Objects in PureBasic easier.
This software helps to keep the coding time small because it does the Class translation
to Structures/Interfaces for you.
Now you can fully concentrate on the task instead of how to use Structures/Interfaces to
make Objects out of it.
Include files can be used. This preprocessor uses all files and compiles them into one.
This is needed for class inheritance. Now you can have your classes nicely packaged into
different files. Just include them and the inheritance works.
The next step would be to create a program/procedure that would delete all unused class
properties and methods to decrease the program size.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The preprocessor takes a Class Declaration and translates into:
1.) Create a Structure for the Properties (Variables)
2.) Create a Interface for the Methods (Procedures)
3.) Declare the Methods
4.) Create a DataSection for the needed Virtual Table
5.) Glue all together and make it work
6.) Takes the Object creation and translates it for each possible type of object:
Variables, Linked Lists and Arrays.
7.) If assigned, execute the constructor at initialization.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Before you will be introduced to Classes lets talk about Structures (user Types).
Most Programming languages can hold Variables and Procedures in Structures.
In PureBasic Strucures can only hold variables.
PureBasic has so called Interfaces to handle Procedures.
Lets take a look at Structures:
Structure MyStructure
MyVar1.l
MyVar2.s
EndStructure
Now lets take a look at Interfaces:
Interface MyInterface
MyProc1()
MyProc2(par.l)
EndStructure
Now lets take a look at Classes as they can be defined with this preprocessor:
Class MyClass
MyVar1.l
MyVar2.s
MyProc1()
MyProc2(par.l)
EndClass
At first sight a class looks like a Structure in other Basic languages, but there is
a main difference.
In other Basic languages the Procedures (called from Structures) need the caller as
first parameter when they need to work with the object, while Procedures from a Class
generated with this preprocessor don't.
This is because PureBasic's Interfaces are more than a Structure in other Basic
languages. (for more information look at the PureBasic help file).
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Lets look again how a Class declaration with this preprocessor looks like:
;class declaration
Class MyClass
My1stProperty
My2ndProperty.l
My1stMethod(par)
My2ndMethod.s()
EndClass
Lets look how a Object creation with this preprocessor looks like, specially look at
the "NEW" keyword that makes it all possible:
;object creation and initialize as variable
myVar.MyClass = New MyClass
;or
;object creation and initialize as global variable
Global myVar.MyClass = New MyClass
;or
;object creation as variable
myVar.MyClass
;initialize
myVar = New MyClass
;or
;object creation as global variable
Global myVar.MyClass
;initialize
myVar = New MyClass
;and work with it with:
With myVar
->My1stMethod(123)
EndWith
myVar->My2ndMethod()
;object creation as Linked List
NewList myList.MyClass()
;or
;object creation as global Linked List
Global NewList myList.MyClass()
;initialize
For i = 0 To 5
AddElement(myList())
myList() = New MyClass
Next
;and work with it with:
FirstElement(myList())
For i = 0 To 5
NextElement(myList())
With myList()
->My1stMethod(i)
EndWith
myList()->My2ndMethod()
Next
;object creation as Array
Dim myArray.MyClass(5)
;or
Global Dim myArray.MyClass(5)
;initialize
For i = 0 To 5
myArray(i) = New myClass
Next
;and work with it with:
For i = 0 To 5
With myArray(i)
->My1stMethod(i)
EndWith
myArray(i)->My2ndMethod()
Next
If there is no type assigned to a property or a return value to a method ".l" (for long)
will be assigned. Methods that don't have LONG as a return need to be declared with a
return type like: GetText.s()
As you can see the object creation looks almost like a normal declaration in PureBasic:
The only different thing is that the "NEW" keyword is used.
This keyword helps the preprocessor to find a line to work with.
Also as with normal initialization, only when using Variables the object creation and
init can be done on one line, because with Lists and Arrays the single Elements need to
be initialized.
The syntax of this preprocessor doesn't want to change PureBasic original syntax or to
force a OOP syntax that is not in harmony with PureBasic's original syntax.
As you can see Variable, Linked List and Array creation didn't change at all.
BTW: the class initialization looks like any other OOP language (examples):
JAVA: MyClass MyObject = new MyClass();
C++: MyClass *MyObject = new MyClass;
or
C++: MyClass *MyObject = new MyClass(1,2);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Double Colon for Class Methods:
Normal Procedures in PureBasic are written as:
Procedure MyProcedure(FirstParameter)
;do something
MyParameter = 123 * FirstParameter
ProcedureReturn MyParameter
EndProcedure
Class methods are written with "Class name" "::" "Method name" like in other oop
languages:
Procedure MyClass::MyMethod()
;do something
*This->MYProperty = 123
EndProcedure
As you can see "->" is used to access the object property. And "This" is used for the
object address pointer.
Lets look at it again, this is used to access a property inside a method:
*This->MYProperty = 123
Finally in the program Methods are called this way:
MyObject->MYMethod()
As you can see "->" is used. Isn't this nice?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Constructor:
Since version 0.5 of this preprocessor it is possible to use a constructor. A constructor
is nothing else than a Method (Procedure) that is called at Object initialization.
A constructor is defined inside the class and needs always the same name as the class:
;class declaration
Class MyClass
My1stProperty
My2ndProperty.l
MyClass() ;<- here is the constructor
My1stMethod(par)
My2ndMethod.s()
EndClass
The Method itself is written as:
Procedure MyClass::MyClass()
;do something
*This->MYProperty = 123
EndProcedure
Lets look at a normal object creation and initialization without a constructor:
;object creation and initialize as variable without constructor
myVar.MyClass = New MyClass
Now lets look at a object creation and initialization with a constructor:
;object creation and initialize as variable with constructor
myVar.MyClass = New MyClass()
As you can see the only difference are the parentesis.
You can pass parameters if you need to, like:
;object creation and initialize as variable with constructor and parameters
myVar.MyClass = New MyClass(par1, par2)
Yes, it's that easy.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Multiple Inheritance:
Inheritance can be defined through the PureBasic Keyword EXTENDS.
Class YourClass
Your1stProperty
Your2ndProperty.l
Your1stMethod()
Your2ndMethod.s()
EndClass
Class MyClass Extends YourClass
My1stProperty
My2ndProperty.l
My1stMethod()
My2ndMethod.s()
EndClass
Inheritance works across all files.
If a class is in an include file you need to inlude the file prior to the use of it.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Multiple Inheritance and constructors:
For now the constructor of the actual class will be started automatically, if defined.
A constructor defined in a inherited class is viewed as a normal method.
If you need to call it, do it yourself:
Class YourClass
Your1stProperty
Your2ndProperty.l
Your1stMethod()
Your2ndMethod.s()
YourClass()
EndClass
Class MyClass Extends YourClass
My1stProperty
My2ndProperty.l
My1stMethod()
My2ndMethod.s()
EndClass
myVar.MyClass = New MyClass ;<- no constructor
myVar->YourClass() ;<- constructor of YourClass is called manually
You could also have 2 constructors:
Class YourClass
Your1stProperty
Your2ndProperty.l
Your1stMethod()
Your2ndMethod.s()
YourClass()
EndClass
Class MyClass Extends YourClass
My1stProperty
My2ndProperty.l
My1stMethod()
My2ndMethod.s()
MyClass()
EndClass
myVar.MyClass = New MyClass() ;<- constructor of MyClass is called at initialization
myVar->YourClass() ;<- constructor of YourClass is called manually
As you can see the constructor of the actual class is called first.
You can call the constructor of the inherited class in the constructor of the new class:
Procedure MyClass::MyClass()
;do something
*This->YourClass() ;<- constructor of YourClass is called manually
EndProcedure
myVar.MyClass = New MyClass() ;<- constructor of MyClass is called at initialization
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Data Encapsulation:
All Properties are private, they need to be accessed through the Methods.
They can't be directly accessed through code like this:
MyObject->MYProperty
This way the properties can't be manipulated that easy, which is less error phrone.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Keywords:
The following keywords should be viewed like PureBasic keywords, use them for the purpose
they are designed:
Class
EndClass
New
This
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Included Files:
For now the commands XIncludeFile and IncludeFile are both treated as IncludeFile.
This means that when the preprocessor finds XIncludeFile the file is always included.
There is no mechanism in place that counts how often a certain Include file is already
included.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Still working on it, but what is decribed in the readme works pretty good so far.
It's the 3rd rewrite of it, so since version 0.7 it's completely written in itself
Besides of the way explained by Netmaestro, you can design you own way (like C++ syntax developed by fsw), or others.
Since i dislike C++ syntax, I like and use this way (example):