summaryrefslogtreecommitdiff
path: root/C/OOP/animal
diff options
context:
space:
mode:
Diffstat (limited to 'C/OOP/animal')
-rw-r--r--C/OOP/animal/animal.c72
1 files changed, 72 insertions, 0 deletions
diff --git a/C/OOP/animal/animal.c b/C/OOP/animal/animal.c
new file mode 100644
index 0000000..01934d7
--- /dev/null
+++ b/C/OOP/animal/animal.c
@@ -0,0 +1,72 @@
+/* Animal class implementation */
+
+#define MAX_NAME_LEN 10
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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();
+}