Object Oriented C – Encapsulation

If you haven’t read my earlier articles on Object Oriented Programming in C (Objects and Polymorphism) I suggest that you go back and read these first.  It isn’t necessary to understand these concepts in order to understand Encapsulation – but it might help give you some background into what I am attempting to achieve here.

To recap, Encapsulation is a means of preventing access to internal object data, ensuring that the data can only be accessed and modified via methods. That’s not to say the internal object data can never be manipulated directly – but one has the option to decide how best the data should be accessed. In explicitly OOP languages this is often achieved through the use of the ‘private’, ‘public’ and ‘protected’ keywords.

C doesn’t have anything even remotely like ‘Private’, ‘Public’ or ‘Protected’ keywords – but we can achieve something similar by bringing a little discipline to our coding practices.  But first, let’s look at what Private, Public and Protected mean.

Private
Private means that the data and methods can only be accessed by the class itself. To use your family as an analogy, this might include your deepest darkest secrets, those that you wouldn’t even admit to your parents. Either that, or the knowledge of what you’re going to get them for Christmas.

Public

Public means that the data and methods can be accessed by anyone. Using the family analogy again, this might include your address.  After all, this information is freely available in the Electoral Register for everyone to see, not just those people that you are related to.

Protected

Protected means that the data and methods can only be accessed by the classes subclasses. Again, using the family analogy, this might be your love for your family.  Your family has your love, but the general public doesn’t.

From this we can see that I’m not very good at analogies.  Let’s see if I’m any better at coding.

Public and Private are quite easy to deal with.  Anything Public we can put in our header – anything Private belongs in the source file.

Header – person.h

typedef struct person_public personPublic;
typedef struct person_public {
    int age;
    char* name;
    char* surname;
    char* address;
}

Source – person.c

#import “person.h”;
typedef struct person_private personPrivate;
typedef struct person_private {
    int creditCardNumber;
    char* deepestDarkestSecret;
}

In this trivial example, any code which imports the person.h file will have access to the data and functions defined therein.  Anything in this h file can therefore be regarded as being public.  The function code will be contained in the person.c source code file, of course, and the data will be manipulated there.

Code and data in the person.c file which doesn’t contain a corresponding definition in the person.h file will not be accessible outside the source code file.  It can therefore be regarded as being private.

So far I don’t think that I’ve had to cheat in any way, or take advantage of any hacks or kludges.  In fact, I don’t even need to rely on the basic human decency of any programmer using this code to play by the rules – good style enforces the rules for me.  Unfortunately, if we want to implement an analogue of protected we need to get a little bit hacky.

C doesn’t understand the concept of ‘protected’ and the only way that I can think of for implementing it is to create a second header file – person_PROTECTED.h.  person_PROTECTED.h will contain any data and functions which should only be accessible to classes which inherit from the parent.  Unfortunately, there’s no mechanism to prevent the PROTECTED header from being imported by code which should only ever have access to the regular public header.  In fact, that’s why I capitalised PROTECTED; that way anyone code reviewing the source knows to pay special attention to whether the PROTECTED header file is allowed to be imported here.
Header – person_PROTECTED.h

typedef struct person_protected personProtected;
typedef struct person_protected {
    int love;
}

The source code, of course, will also need to import this header, becoming:
Source – person.c

#import “person.h”;
#import “person_PROTECTED.h”;
typedef struct person_private personPrivate;
typedef struct person_private {
    int creditCardNumber;
    char* deepestDarkestSecret;
}

So there you have it.  Encapsulation, C style.

CategoriesUncategorised

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.