DEFCLASS

General Form:

Where:
defsub

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.

Full DEFCLASS example


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