Menu
Coddy logo textTech

Implementare le interfacce

Fa parte della sezione Programmazione orientata agli oggetti del percorso C di Coddy. Lezione 41 di 61.

Ora che hai capito cos'è un'interfaccia, una struct che contiene solo puntatori a funzione, è il momento di creare implementazioni concrete che rispettino quel contratto.

Ricorda la nostra interfaccia ILogger della lezione precedente:

typedef void (*LogFunc)(const char* message);

typedef struct {
    LogFunc log;
} ILogger;

Per implementare questa interfaccia, scriviamo funzioni effettive che corrispondono alla firma di LogFunc, poi creiamo istanze di ILogger assegnando loro queste funzioni:

void console_log(const char* message) {
    printf("[CONSOLE] %s\n", message);
}

void file_log(const char* message) {
    printf("[FILE] %s\n", message);  // Simulazione dell'output su file
}

ILogger create_console_logger() {
    ILogger logger = { console_log };
    return logger;
}

ILogger create_file_logger() {
    ILogger logger = { file_log };
    return logger;
}

Ogni funzione "costruttrice" restituisce un ILogger con una funzione diversa collegata. Il codice che usa questi logger non deve sapere quale implementazione ha ricevuto:

void do_work(ILogger* logger) {
    logger->log("Starting work...");
    logger->log("Work complete!");
}

int main() {
    ILogger console = create_console_logger();
    ILogger file = create_file_logger();
    
    do_work(&console);  // Usa console_log
    do_work(&file);     // Usa file_log
    return 0;
}

La funzione do_work è completamente disaccoppiata dall’implementazione della registrazione. Puoi sostituire liberamente i logger senza modificare la logica di base: questo è il potere della programmazione basata su un’interfaccia.

challenge icon

Sfida

Facile

Costruiamo un sistema INotifier che mostra come implementazioni diverse possano rispettare lo stesso contratto di interfaccia. Creerai notificatori concreti, un EmailNotifier e un SMSNotifier, conformi entrambi a un'interfaccia comune ma in grado di produrre output diversi.

Organizzerai il codice in tre file:

  • notifier.h: definisci qui l'interfaccia. Crea un tipo puntatore a funzione chiamato NotifyFunc che accetta un messaggio const char* e non restituisce nulla. Definisci poi una struct INotifier contenente solo un puntatore a funzione notify di questo tipo. Dichiara inoltre due funzioni costruttrici: create_email_notifier e create_sms_notifier, ciascuna delle quali restituisce un INotifier per valore.
  • notifier.c: implementa qui le funzioni concrete di notifica e le funzioni costruttrici. Crea:
    • email_notify: stampa il messaggio nel formato: [EMAIL] message
    • sms_notify: stampa il messaggio nel formato: [SMS] message
    • create_email_notifier: restituisce un INotifier collegato a email_notify
    • create_sms_notifier: restituisce un INotifier collegato a sms_notify
  • main.c: riunisci qui tutti gli elementi. Leggi un tipo di notifica e un messaggio, crea il notificatore appropriato usando le funzioni costruttrici e invia la notifica tramite l'interfaccia.

Il programma riceverà due input: un tipo di notifica (1 per email, 2 per SMS) e un messaggio da inviare.

Usa le funzioni costruttrici per creare il notificatore appropriato, poi chiama notify tramite l'interfaccia per visualizzare il messaggio.

Output di esempio quando il tipo è 1 e il messaggio è Meeting at 3pm:

[EMAIL] Meeting at 3pm

Output di esempio quando il tipo è 2 e il messaggio è Your code shipped:

[SMS] Your code shipped

Il vantaggio di questo schema è che main.c non deve sapere come funziona internamente ciascun notificatore. Chiama semplicemente la funzione notify dell'interfaccia e viene eseguita l'implementazione corretta. Ricorda di usare le guardie di inclusione nel file header.

Provalo tu

#include <stdio.h>
#include "notifier.h"

int main() {
    int type;
    char message[256];
    
    // Lee el tipo de notificación (1 para correo electrónico, 2 para SMS)
    scanf("%d", &type);
    getchar(); // consume el salto de línea
    
    // Lee el mensaje
    fgets(message, sizeof(message), stdin);
    // Elimina el salto de línea final si está presente
    int len = 0;
    while (message[len] != '\0') len++;
    if (len > 0 && message[len-1] == '\n') message[len-1] = '\0';
    
    // TODO: Crea el notificador adecuado según type
    // Usa create_email_notifier() para type 1
    // Usa create_sms_notifier() para type 2
    
    // TODO: Llama a la función notify a través de la interfaz
    // notifier.notify(message);
    
    return 0;
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore C online