/* Animal class implementation */ #define MAX_NAME_LEN 10 #include #include #include #include "animal_priv.h" struct animal * animal_new() { return (struct animal *)malloc(sizeof(struct animal)); } /* * By passing the custom sound function to the constructor, we prevent the need to expose the * Animal's private interface to the sub-class * * This is an attempt to get as much abstraction as possible of a C program. * The sub-class has no business in understanding the inner functionality of the parent class, * so, this is an attempt to hide the animal implementation as much as possible from the sub-class. */ void animal_ctor(struct animal *animal, void (*sound_fn)(void)) { animal->name = malloc(MAX_NAME_LEN * sizeof(char)); if (sound_fn) animal->make_sound = sound_fn; else animal->make_sound = NULL; } void animal_dtor(struct animal *animal) { free(animal->name); } void animal_get_name(struct animal *animal, char *name) { strncpy(name, animal->name, MAX_NAME_LEN); } void animal_set_name(struct animal *animal, const char *name) { if (strlen(name) >= MAX_NAME_LEN) strncpy(animal->name, "\0", 1); else strncpy(animal->name, name, MAX_NAME_LEN); } /* * To be able to access the object specific implementation of make_sound(), * this function should somehow access the function pointer to the * object-specific implementation. * * This could be done in two ways: * - By having the Animal object embedded within the sub-class, so both * the Animal object and the Sub-Class object will share the same address * in memory, or: * - We add an 'ops' field in the Animal object, which should be populated * by the sub-class. * * In both ways, there is no way to really hide the Animal implementation from * the sub-class, as in one way or another, we'll need to have access to the * Animal class fields, so we can override the functions. */ void animal_sound(struct animal *animal) { if (animal->make_sound) animal->make_sound(); }