#include #include // Here's a basic interface for geometric shapes. typedef struct { double (*area)(void *); double (*perim)(void *); } geometry; // For our example we'll implement this interface on // `rect` and `circle` types. typedef struct { double width, height; } rect; typedef struct { double radius; } circle; // To implement an interface in C, we need to define functions // that match the function pointers in the interface. // Here we implement `geometry` on `rect`s. double rect_area(void *r) { rect *rect_ptr = (rect *)r; return rect_ptr->width * rect_ptr->height; } double rect_perim(void *r) { rect *rect_ptr = (rect *)r; return 2 * rect_ptr->width + 2 * rect_ptr->height; } // The implementation for `circle`s. double circle_area(void *c) { circle *circle_ptr = (circle *)c; return M_PI * circle_ptr->radius * circle_ptr->radius; } double circle_perim(void *c) { circle *circle_ptr = (circle *)c; return 2 * M_PI * circle_ptr->radius; } // If a variable has an interface type, then we can call // methods that are in the named interface. Here's a // generic `measure` function taking advantage of this // to work on any `geometry`. void measure(void *g, geometry *geom) { printf("Area: %f\n", geom->area(g)); printf("Perimeter: %f\n", geom->perim(g)); } int main() { rect r = {.width = 3, .height = 4}; circle c = {.radius = 5}; // The `circle` and `rect` struct types both // implement the `geometry` interface so we can use // instances of these structs as arguments to `measure`. geometry rect_geometry = {rect_area, rect_perim}; geometry circle_geometry = {circle_area, circle_perim}; printf("Rectangle:\n"); measure(&r, &rect_geometry); printf("\nCircle:\n"); measure(&c, &circle_geometry); return 0; }