CPlay/interfaces.c
2025-12-27 02:09:32 +01:00

70 lines
1.8 KiB
C

#include <math.h>
#include <stdio.h>
// 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;
}