Menu
Coddy logo textTech

Iteracja polimorficzna

Część sekcji Programowanie obiektowe ścieżki C w Coddy. Lekcja 42 z 61.

Nauczyłeś się tworzyć interfejsy i implementować je za pomocą różnych konkretnych funkcji. Prawdziwa korzyść pojawia się wtedy, gdy możesz traktować kolekcję różnych obiektów jednolicie: iterować po nich i wywoływać na każdym ten sam wskaźnik do funkcji, niezależnie od tego, jakie konkretne zachowanie jest z nim powiązane.

Wyobraź sobie, że masz tablicę struktur Action, z których każda ma przypisaną własną funkcję execute:

typedef void (*ExecuteFunc)(void);

typedef struct {
    const char* name;
    ExecuteFunc execute;
} Action;

void jump(void) { printf("Jumping!\n"); }
void run(void)  { printf("Running!\n"); }
void rest(void) { printf("Resting...\n"); }

Możesz utworzyć tablicę tych działań, z których każde jest powiązane z inną funkcją, a następnie przejść przez nią za pomocą prostej pętli for:

int main() {
    Action actions[3] = {
        { "Jump", jump },
        { "Run", run },
        { "Rest", rest }
    };
    
    for (int i = 0; i < 3; i++) {
        printf("%s: ", actions[i].name);
        actions[i].execute();
    }
    return 0;
}

Pętla nie wie ani nie interesuje się tym, co każda akcja robi wewnętrznie. Po prostu wywołuje execute() dla każdego elementu.

To polimorfizm w działaniu: ten sam kod obsługuje obiekty o zupełnie różnych zachowaniach. Dodanie nowego typu działania nie wymaga żadnych zmian w logice iteracji; wystarczy dodać kolejny element do tablicy.

challenge icon

Wyzwanie

Łatwy

Zbudujmy system zarządzania Task, który demonstruje iterację polimorficzną: przetwarzanie kolekcji obiektów współdzielących wspólny interfejs, ale wykonujących różne działania.

Rozmieścisz kod w trzech plikach:

  • task.h: Zdefiniuj tutaj interfejs zadań. Utwórz typ wskaźnika do funkcji o nazwie TaskFunc, która nie przyjmuje parametrów i niczego nie zwraca. Następnie zdefiniuj strukturę Task zawierającą name (typu const char*) oraz wskaźnik do funkcji run typu TaskFunc.
  • task.c: Zaimplementuj trzy różne funkcje zadań reprezentujące różne rodzaje pracy:
    • backup_task: wyświetla Backing up data...
    • cleanup_task: wyświetla Cleaning up files...
    • report_task: wyświetla Generating report...
  • main.c: Połącz tutaj wszystkie elementy. Utwórz tablicę struktur Task, z których każda jest powiązana z inną funkcją zadania. Następnie wykonaj iterację po tablicy i uruchom każde zadanie polimorficznie; dla każdego zadania wyświetl jego nazwę, a następnie wywołaj jego funkcję run.

Program otrzyma jedno dane wejściowe: liczbę zadań do uruchomienia (1, 2 lub 3).

Utwórz tablicę zawierającą dokładnie trzy zadania w następującej kolejności: zadanie tworzenia kopii zapasowej o nazwie Backup, zadanie czyszczenia o nazwie Cleanup oraz zadanie generowania raportu o nazwie Report. Na podstawie podanej liczby wykonaj iterację tylko po tej liczbie zadań, zaczynając od początku tablicy.

Dla każdego zadania w iteracji wyświetl jego nazwę, a po niej dwukropek i spację, a następnie wywołaj jego funkcję run.

Przykładowy wynik, gdy dane wejściowe to 2:

Backup: Backing up data...
Cleanup: Cleaning up files...

Przykładowy wynik, gdy dane wejściowe to 3:

Backup: Backing up data...
Cleanup: Cleaning up files...
Report: Generating report...

Kluczowa wskazówka jest taka, że pętla nie musi wiedzieć, co robi każde zadanie. Po prostu wyświetla nazwę i wywołuje run() dla każdego elementu. Ten sam kod iteracji obsługuje jednakowo wszystkie typy zadań. Pamiętaj, aby użyć osłon przed wielokrotnym dołączaniem w pliku nagłówkowym.

Spróbuj swoich sił

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

// Zadeklaruj funkcje zadań zaimplementowane w task.c
void backup_task(void);
void cleanup_task(void);
void report_task(void);

int main() {
    int count;
    scanf("%d", &count);
    
    // TODO: Utwórz tablicę 3 struktur Task w tej kolejności:
    // 1. Zadanie tworzenia kopii zapasowej o nazwie "Backup", używające backup_task
    // 2. Zadanie czyszczenia o nazwie "Cleanup", używające cleanup_task
    // 3. Zadanie tworzenia raportu o nazwie "Report", używające report_task
    
    // TODO: Przejdź przez 'count' zadań z tablicy
    // Dla każdego zadania wypisz: "<name>: ", a następnie wywołaj jego funkcję run
    
    return 0;
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator C online