| By: | Abdul Habra |
| Email: | ahabra@yahoo.com |
| Version: | 0.1 |
| Date: | October 1995 |
Note: This article was published originally in the Cap Gemini America - Cincinnati Unit Newsletter.
This is the second article in a series on Object Oriented programming techniques using ‘C’. In the previous installment of this series of articles I explained how to use ‘C’ to define a class. The DISTANCE class was used as an example. In this installment encapsulation will be presented including how to define public and private members of a class. Encapsulation is the ability to hide the internal implementation details of an object from the outside world.
This section provides a brief explanation of some ‘C’ constructs that will be used later to support encapsulation.
A static function is a function that is only visible in the file that contains it. A static function is defined by adding the word static at the beginning of the function definition. For example, if we have a file called test1.c that has the function:
static int square(int x) { return x*x; }
then the only functions that can use square() are functions defined in the file test1.c
Casting provides the ability to convert a value to a different type. To cast an expression, put the target data type in parentheses directly before the expression. For example:
float x; x= (float) 1;
assigns the int value 1 to the float variable x. In the previous installment we used casting in the constructor:
DISTANCE* ob=(DISTANCE*) calloc(1, sizeof(DISTANCE));
The calloc() function returns a void pointer, and we cast it to DISTANCE pointer in order to assign this value to ob without the compiler generating any warning messages.
In summary, if we have the cast: (MyType)MyValue we will be telling the compiler to treat MyValue as if it is of type MyType.
We need to have a facility in which the methods of a class can only be accessed through the class. Additionally, the class may have members that should not be visible outside the class definition, i.e. private.
For a class, only its definition should be visible by the class’ users. The implementation of the class should be completely hidden. The solution is simple:
For our DISTANCE class, put the class definition (i.e. struct) in distance.h, put the implementation of its methods in distance.c and make all the methods static (except ConstructDistance). For example:
static float DistanceKm(DISTANCE* this) {
return this->DistanceMiles*1.609;
}
Although the class implementation is hidden from its users, all the class members are accessible by anyone who uses this class. We need to have a mechanism in which some of the class’s members are inaccessible by the class users. In our DISTANCE class, suppose we want to be able to set and get the distance in both units of Miles or Kilometer.
distance.h
typedef struct { void* private; void (*Destructor)(); void (*SetMiles)(); float (*GetMiles)(); void (*SetKm)(); float (*GetKm)(); } DISTANCE; DISTANCE* ConstructDistance();Notice that there is no data member to store the distance value in the class definition. Additionally, there is a void pointer named private.
typedef struct { float DistanceMiles; } PrivateType;Put in this PrivateType all the class members that you wish to make private.
ob->private= calloc(1, sizeof(PrivateType));
free((*this)->private);
static void SetMiles(DISTANCE* this, float miles) { PrivateType* p= (PrivateType*)this->private; p->DistanceMiles= miles; }Notice how private -which is a void pointer- is casted to a PrivateType pointer.
It is shown here that with utilizing some standard ‘C’ constructs we are capable of supporting encapsulation. This is achieved with a simple approach. Mainly, define all methods implementation to be static and have a class member that the user can not change (private). In the next installment of this series of articles, I will discuss inheritance and polymorphism then see if we could implement them using ‘C’.
I would like to thank both of Carol Viera and Srinivasa Komatineni for their review and suggestions.
| Page Last Updated 1995.10.01 |
|