-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathAnimal.c
More file actions
96 lines (69 loc) · 1.89 KB
/
Animal.c
File metadata and controls
96 lines (69 loc) · 1.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "Animal.h"
/** Duplicates a null-terminated string like the POSIX function but gracefully handles NULL.
*/
char* strdup2(const char* s) {
if (!s)
return NULL;
size_t len = strlen(s);
char* s2 = (char*) malloc(len + 1);
memcpy(s2, s, len + 1);
return s2;
}
// Animal
struct Animal {
int legs;
};
DEFINE_CLASS(Animal, (), (), {
Animal* data = (Animal*) calloc(1, sizeof(Animal));
PUSH_CLASS(self, Animal, data);
PUSH_METHOD(self, Animal, Animal, speak);
PUSH_ACCESSOR(self, Animal, Animal, legs);
}, {
printf("bye Animal\n");
free(data);
})
DEFINE_METHOD_CONST_VIRTUAL(Animal, speak, void, (), VOID, (), {
printf("I'm an animal with %d legs.\n", GET(self, Animal, legs));
})
DEFINE_ACCESSOR_VIRTUAL_AUTOMATIC(Animal, legs, int, -1)
DEFINE_METHOD_CONST(Animal, pet, void, (), VOID, {
printf("You pet the animal.\n");
})
// Dog
struct Dog {
char* name;
};
DEFINE_CLASS(Dog, (const char* name), (name), {
SPECIALIZE(self, Animal);
Dog* data = (Dog*) calloc(1, sizeof(Dog));
PUSH_CLASS(self, Dog, data);
PUSH_METHOD(self, Animal, Dog, speak);
PUSH_ACCESSOR(self, Animal, Dog, legs);
PUSH_ACCESSOR(self, Dog, Dog, name);
SET(self, Animal, legs, 4);
SET(self, Dog, name, name);
}, {
printf("bye Dog\n");
free(data->name);
free(data);
})
DEFINE_METHOD_CONST_OVERRIDE(Dog, speak, void, (), VOID, {
printf("Woof, I'm a dog named %s with %d legs.\n", GET(self, Dog, name), GET(self, Animal, legs));
})
// This example is a bit pointless, but it demonstrates how to call the superclass' method from an overridden method.
DEFINE_ACCESSOR_OVERRIDE(Dog, legs, int, -1, {
return GET_SUPER(self, Animal, Dog, legs);
}, {
if (legs > 4)
legs = 4;
SET_SUPER(self, Animal, Dog, legs, legs);
})
DEFINE_ACCESSOR_VIRTUAL(Dog, name, const char*, "", {
return data->name;
}, {
free(data->name);
data->name = strdup2(name);
})