Created
July 12, 2012 17:44
-
-
Save dskinner/3099588 to your computer and use it in GitHub Desktop.
Polymorphic behaviour 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
#include <stdio.h> | |
#include <stdlib.h> | |
// | |
typedef struct Duck Duck; | |
typedef void (*quack_t)(void *self); | |
void Duck_quack(void *self); | |
// Overriding original structure members means you must include everything up. | |
// So if I want to override `quack`, I dont need to override anything | |
// else. If I want to override `quacked`, I must override `quack` also. | |
struct Duck { | |
quack_t quack; | |
int quacked; | |
}; | |
Duck *Duck_create() | |
{ | |
Duck *d = malloc(sizeof(Duck)); | |
d->quack = Duck_quack; | |
d->quacked = 0; | |
return d; | |
} | |
void Duck_destroy(Duck *duck) | |
{ | |
free(duck); | |
} | |
void Duck_quack(void *self) | |
{ | |
Duck *d = self; | |
if(d->quacked) { | |
printf("already quacked\n"); | |
} else { | |
printf("quack\n"); | |
} | |
d->quacked = 1; | |
} | |
// | |
typedef struct Bird Bird; | |
void Bird_quack(void *self); | |
struct Bird { | |
// Overrides have to align in memory so this comes first | |
quack_t quack; | |
// Specific to bird | |
Duck *duck; // we keep this to track quacked without overriding | |
int a; | |
}; | |
Bird *Bird_create() | |
{ | |
Bird *b = malloc(sizeof(Bird)); | |
b->quack = Bird_quack; | |
Duck *d = malloc(sizeof(Duck)); | |
b->duck = d; | |
b->a = 0; | |
return b; | |
} | |
void Bird_destroy(Bird *b) | |
{ | |
free(b->duck); | |
free(b); | |
} | |
void Bird_quack(void *self) | |
{ | |
Bird *b = self; | |
// just some sillyness on Bird alloc | |
if(b->duck->quacked) { | |
b->a += 20; | |
} else { | |
b->a++; | |
} | |
// here we have to account for how the super method (basically) | |
// also edits `quacked` but we didn't override it. So we pass | |
// in our struct Duck alloc so we can call the original method | |
// and have `quacked` available for use (essentially public). | |
Duck_quack(b->duck); | |
// can't do this since addition of `quacked` and I intentionally | |
// didn't track that in struct Bird | |
//Duck_quack(self); | |
// show progression of `a` | |
printf("a: %d\n", b->a); | |
} | |
// | |
void quack_it(void *obj) | |
{ | |
Duck *d = obj; | |
d->quack(d); | |
} | |
int main(int argc, char *argv[]) | |
{ | |
Bird *b = Bird_create(); | |
quack_it(b); | |
quack_it(b); | |
Duck *d = Duck_create(); | |
quack_it(d); | |
Duck_destroy(d); | |
Bird_destroy(b); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment