Hello, inheritance; Hello, constructors; Hello static context

Because we can stack these things, we can stack whatever the hell we want, so long as we’re consistent. All Java objects inherit the Object class, so let’s create our own:

struct Object{

void *(*New)(); //You can implement arguments

//to this function however you want, using

//varargs or void *, etc.

};

Simple. Just takes a void pointer to a constructor function. To implement these, Public scope structs must include them as members. Actually, this object only needs to be implemented by a single object once, so you can implement this as an anonymous union if you want, so that subsequent objects can use this memory space for other variables.

struct Cat{

struct Object Parent;

// Other members...

};

What does this do for us? We can create a constructor function like so:

void *ConstructCat(){

struct PrivateCat *this = malloc(sizeof(struct PrivateCat));

this->PublicScope.ClawLength = 9;

this->PublicScope.GetClawLength = _GetClawLength;

this->PublicScope.GetNumLives = _GetNumLives;

this->PublicScope.SetNumLives = _SetNumLives;

this->NumLives = 9;

return PrivateCat;

}

For syntactic sugar, and to support a “static” context, we do two things: create a “new” function, and create a “static” object, or a global variable for that class that we can call by a name recognizable as being in the “static” context.

//We have to declare the constructor before

//the struct so that we can initialize the static

//cat right after defining the struct.

void *ConstructCat();

struct Cat{

struct Object Parent;

//Members go here

} StaticCat = {

.Parent.New = ConstructCat

//Define whatever static variables you want in here

//so that you can call them as `StaticCat.ClawLength`

//These won't be purely static however, as instantiations

//will have their own copies, but they do give a global

//context for these member variables

};

Here’s where the magic of inheritance comes into play: because the compiler stacked the structs on top of each other in the order we defined them, we can cast any struct which implements the Object struct to (struct Object *) and then call the constructor from there:

void *new(void *Template){

return ((struct Object*)Template)->New();

}

Which enables this:

struct Cat *Ian = new(&StaticCat);

For added comfort, choose your own naming convention so that it makes more sense to you. If you want, you can work it into “new(&Cat)”.

Of course, you’ll need to write destructors and methods which free the largest size pointer you allocate (private in this case). Also, nothing is stopping the developer from casting whatever pointers she wants to the private form and accessing variables this way, but this is how C works, of course.

A final look at an implementation in a file “CatClass.c” might look like

//Declare Constructor before structs

void *ConstructCat();

struct Cat{

struct Object Parent;

int ClawLength;

int (*GetClawLength)(void *);

int (*GetNumLives)(void *);

} StaticCat = {

.Parent.New = ConstructCat

}; //instantiate this as a private cat if you want static

//access to private variables for some reason...

struct PrivateCat{

struct Cat PublicScope;

int NumLives;

}; int _GetClawLength(void *this);

int _GetNumLives(void *this); void *ConstructCat(){

struct PrivateCat *this = malloc(sizeof(struct PrivateCat));

this->PublicScope.ClawLength = 8;

this->PublicScope.GetClawLength = _GetClawLength;

this->PublicScope.GetNumLives = _GetNumLives;

this->NumLives = 9;

} int _GetClawLength(void *this){

return ((struct Cat *)this)->ClawLength;

}

int _GetNumLives(void *this){

return ((struct PrivateCat *)this)->NumLives;

}

The ObjectClass.c file would simply be

struct Object{

void *(*New)();

};

void *new(void *Template){

return ((struct Object*)Template)->New();

}

and main.c: