DEFCLASS
General Form:
Note: Experimental. Following is subject to change.
DEFCLASS is one of the KCML language constructs that allows KCML to provide an object oriented programming model. The DEFCLASS construct defines a class of object that we can then create instances of. It is a natural extension of the DEFSTRUCT construct.
To defined a DEFCLASS you use the DEFCLASS/ENDCLASS statements to mark the start and end of the definition. Everything between these two statements should form part of the DEFCLASS definitition.
Members
A DEFCLASS can contain two types of member definitions. Data members (FLD) and methods (DEFMETHOD). To access a class member we use the -> operator. Unlike DEFRECORD/DEFSTRUCT the member names are placed in their own class namespace.
Data members
Using FLD statements we can specify data members. This is almost identical to DEFRECORD/DEFSTRUCT.
Defining:
DEFCLASS myClass FLD member$ ENDCLASS
The above class contains a single string member.
It is possible to initialise some members inline in the definition statement. The member must be a class instance.
DEFCLASS myClass FLD member as myOtherClass = new myOtherClass ENDCLASS
When an instance of myClass is created the member variable member has an instance of myOtherClass assigned. This will occur before the constructor is called.
Accessing member:
LOCAL DIM p AS ClassName p = NEW ClassName p->member$ = "example"
There are a few changes associated with data members in DEFCLASSs.
Methods
This is specified in a similar way to DEFSUB. To call a method you use the -> operator. Every DEFMETHOD is virtual. This mean that its possible to override the DEFMETHOD by defining another class that inherits from this class.
Defining:
DEFCLASS myBaseClass DEFMETHOD 'vMethod() ENDMETHOD ENDCLASS
The above class contains a single method that returns nothing.
A DEFMETHOD has a built in variable this. The this variable represents the object instance for the method being called. This will allow access to the instances member variables.
DEFCLASS myBaseClass FLD f_n DEFMETHOD 'vMethod() this->f_n = 101 ENDMETHOD ENDCLASS
Calling method:
LOCAL DIM p AS ClassName p = NEW ClassName p->method()
SUPER
Within DEFMETHODs it is also possible to use the keyword SUPER. This allows access to the superclass methods.
DEFCLASS myBaseClass DEFMETHOD 'vMethod() ENDMETHOD ENDCLASS DEFCLASS myClass EXTENDS CLASS myBaseClass DEFMETHOD 'vMethod() super->vMethod() ENDMETHOD ENDCLASS
In this example myClass vMethod makes a call to myBaseClass vMethod.
Special Methods
Constructor:
DEFCLASS myBaseClass DEFMETHOD Constructor() ENDMETHOD ENDCLASS
Is called when a instance of that class is created.
Destructor:
DEFCLASS myBaseClass DEFMETHOD Destructor() ENDMETHOD ENDCLASS
Is called when a instance of that class is destroyed.
Inheritance
A DEFCLASS can inherit the members of a single DEFCLASS. It can also replace the DEFMETHODs from the DEFCLASS it inherits from.
DEFCLASS myBaseClass DEFMETHOD 'vMethod() PRINT "1" ENDMETHOD ENDCLASS DEFCLASS myClass EXTENDS CLASS myBaseClass DEFMETHOD 'vMethod() PRINT "2" ENDMETHOD ENDCLASS DEFSUB 'Main() LOCAL DIM p AS myBaseClass p = NEW myClass p->vMethod() ENDSUB
In this case a value of 2 will be printed because vMethod from myClass will be called because p contains an instance of myClass even though it is typed as myBaseClass.
Accessibility
It is possible to specify the accessibility of each member. There are three access levels
PUBLIC DEFMETHOD 'vMethod() PROTECTED DEFMETHOD 'vMethod() PRIVATE DEFMETHOD 'vMethod2()
Instances
Creating an instance
To create an object instance we use the NEW keyword followed by the name of the class that you wish to create.
LOCAL DIM p AS ClassName p = NEW ClassName
This example would create an instance of ClassName using the local POOL. An object instance is always allocated against a pool. When a pool is detroyed all the objects attached to it will be destroyed as well.
Destroying an instance
To destroy an object instance we use the DELETE PTR keyword followed by the instance variable.
LOCAL DIM p AS ClassName p = NEW ClassName DELETE PTR p
Example
$COMPLIANCE 3 DIM g_Id=1 // // CShape. // PRIVATE DEF CLASS CShape PRIVATE FLD m_nId PUBLIC DEFMETHOD Constructor() this->m_nId = g_Id++ END METHOD DEFMETHOD GetId() RETURN this->m_nId END METHOD DEFMETHOD DisplayName() PRINT this->Getname$() END METHOD END CLASS // // Triangle // PRIVATE DEF CLASS CTriangle EXTENDS CLASS CShape DEFMETHOD GetSides() RETURN 3 END METHOD DEFMETHOD GetName$() RETURN "Triangle" END METHOD END CLASS // // Rectangle // PRIVATE DEF CLASS CRectangle EXTENDS CLASS CShape DEFMETHOD GetSides() RETURN 4 END METHOD DEFMETHOD GetName$() RETURN "Rectangle" END METHOD END CLASS // // Square // PRIVATE DEF CLASS CSquare EXTENDS CLASS CRectangle PUBLIC DEFMETHOD GetName$() RETURN "Square" END METHOD END CLASS 'Main() $END DEFSUB 'Display(pShape AS CShape) pShape->Displayname() PRINT pShape->GetSides() PRINT pShape->GetId() END SUB DEFSUB 'Main() LOCAL DIM pShape AS CShape LOCAL DIM pList AS PTR(X$_KCML_ListClass) pList = NEW PTR(X$_KCML_ListClass) pShape = NEW CTriangle 'Display(pShape) pList->Add(pShape) pShape = NEW CRectangle 'Display(pShape) pList->Add(pShape) pShape = NEW CSquare 'Display(pShape) pList->Add(pShape) END SUB
Status
Experimental.
Compatibility
Introduced with KCML 7.05.
See also:
DEFRECORD, DEFSTRUCT, DEFSUB, NEW, Tutorial on memory pooling