Last active
November 19, 2015 06:59
-
-
Save ryjen/4180753 to your computer and use it in GitHub Desktop.
Poor Man's Polymorphism in C
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* | |
* Poor mans polymorphism | |
* | |
* c0der78 (www.arg3.com) | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <time.h> | |
typedef struct vehicle Vehicle; | |
typedef struct car Car; | |
typedef struct plane Plane; | |
/** | |
* The "Base" structure | |
* sub structures must implement the exact type and order to cast it | |
*/ | |
struct vehicle | |
{ | |
int key; | |
void (*onStart)(Vehicle *); | |
}; | |
/** | |
* Has the same field order as Vehicle plus additional info | |
*/ | |
struct car | |
{ | |
int key; | |
void (*onStart)(Vehicle *); | |
int doors; | |
int tires; | |
}; | |
/** | |
* Has the same field order as Vehicle plus additional info | |
*/ | |
struct plane | |
{ | |
int key; | |
void (*onStart)(Vehicle *); | |
int engines; | |
}; | |
/** | |
* This handles common code between a Car and a Plane | |
*/ | |
void start_vehicle(Vehicle *this, int key, const char *vehicleName, const char *keyName) | |
{ | |
// check for the right key | |
if(this->key == key) { | |
printf("%s fits %s\n", keyName, vehicleName); | |
this->onStart(this); | |
} | |
else | |
{ | |
printf("%s does not fit %s\n", keyName, vehicleName); | |
} | |
} | |
/** | |
* callback when a car is started | |
*/ | |
void car_started(Vehicle *this) | |
{ | |
// cast back to a car | |
Car *car = (Car*) this; | |
printf("the car has %d doors and %d tires\n", car->doors, car->tires); | |
} | |
/** | |
* callback when a plane is started | |
*/ | |
void plane_started(Vehicle *this) | |
{ | |
// cast back to a plane | |
Plane *plane = (Plane *) this; | |
printf("the plane has %d engines\n", plane->engines); | |
} | |
/** | |
* Output: | |
* | |
* key1 fits volkswagon | |
* the car has 4 doors and 4 tires | |
* key2 does not fit volkswagon | |
* key1 does not fit b52 | |
* key2 fits b52 | |
* the plane has 6 engines | |
*/ | |
int main(int argc, char *argv[]) | |
{ | |
srand(time(0)); | |
int key1 = rand() % 10000 + 1; | |
int key2 = rand() % 10000 + 1; | |
// init a car | |
Car volkswagon; | |
volkswagon.key = key1; | |
volkswagon.doors = 4; | |
volkswagon.tires = 4; | |
volkswagon.onStart = car_started; | |
// init a plane | |
Plane b52; | |
b52.key = key2; | |
b52.engines = 6; | |
b52.onStart = plane_started; | |
// test. this is really what the magic is all about. We can cast a Car structure | |
// to a Vehicle structure because the field type and order is the same | |
start_vehicle((Vehicle*) &volkswagon, key1, "volkswagon", "key1"); | |
start_vehicle((Vehicle*) &volkswagon, key2, "volkswagon", "key2"); | |
// again we can cast a Plane structure to a Vehicle structure because | |
// the field type and order is the same | |
start_vehicle((Vehicle*) &b52, key1, "b52", "key1"); | |
start_vehicle((Vehicle*) &b52, key2, "b52", "key2"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment