Stages 4–5

OOP Thinking in C

Objects, methods, self, encapsulation, opaque handles, and clean lifecycle management — without a class keyword in sight.

4.1 struct = object; functions = methods

led.h
typedef struct LedState LedState;

LedState *Led_Create(uint8_t id);
void      Led_SetBrightness(LedState *self, uint8_t brightness);
void      Led_Toggle(LedState *self);
void      Led_Destroy(LedState *self);

5.1 Opaque handles

led.c — struct defined only here
struct LedState {
    uint8_t  id;
    uint8_t  brightness;
    bool     on;
    uint32_t color;
};

LedState *Led_Create(uint8_t id) {
    LedState *s = malloc(sizeof *s);
    if (!s) return NULL;
    *s = (LedState){ .id=id, .brightness=100, .on=false };
    return s;
}

Callers only see the pointer — internals are invisible. Changing the struct never breaks callers as long as the API stays the same.