Iteração Polimórfica
Parte da seção Object Oriented Programming do Journey de C da Coddy — lição 42 de 61.
Você aprendeu a criar interfaces e implementá-las com diferentes funções concretas. A verdadeira vantagem surge quando você pode tratar uma coleção de diferentes objetos de forma uniforme — iterando por eles e chamando o mesmo ponteiro de função em cada um, independentemente de qual comportamento específico esteja configurado.
Imagine que você tem um array de Action structs, cada uma com sua própria função execute atribuída:
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"); }Você pode criar um array dessas ações, cada uma conectada a uma função diferente, e então percorrê-las com um loop for simples:
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;
}O loop não sabe nem se importa com o que cada ação faz internamente. Ele simplesmente chama execute() em cada elemento.
Isso é polimorfismo em ação — o mesmo código lida com objetos com comportamentos completamente diferentes. Adicionar um novo tipo de ação não requer alterações na lógica de iteração; você apenas adiciona outro elemento ao array.
Desafio
FácilVamos construir um sistema de gerenciamento de Task que demonstra iteração polimórfica — processando uma coleção de objetos que compartilham uma interface comum, mas executam comportamentos diferentes.
Você organizará seu código em três arquivos:
task.h: Defina sua interface de tarefa aqui. Crie um tipo de ponteiro de função chamadoTaskFuncque não recebe parâmetros e não retorna nada. Em seguida, defina uma structTaskcontendo umname(umconst char*) e um ponteiro de funçãorundo tipoTaskFunc.task.c: Implemente três funções de tarefa diferentes que representam diferentes tipos de trabalho:backup_task— imprimeBacking up data...cleanup_task— imprimeCleaning up files...report_task— imprimeGenerating report...
main.c: Reúna tudo aqui. Crie um array de structsTask, cada uma vinculada a uma função de tarefa diferente. Em seguida, itere pelo array e execute cada tarefa de forma polimórfica — para cada tarefa, imprima seu nome seguido pela chamada de sua funçãorun.
Seu programa receberá uma única entrada: o número de tarefas a serem executadas (1, 2 ou 3).
Crie um array contendo exatamente três tarefas nesta ordem: uma tarefa de backup chamada Backup, uma tarefa de limpeza chamada Cleanup e uma tarefa de relatório chamada Report. Com base na contagem de entrada, itere apenas por esse número de tarefas a partir do início do array.
Para cada tarefa em sua iteração, imprima o nome da tarefa seguido por dois pontos e um espaço, e então chame sua função run.
Exemplo de saída quando a entrada é 2:
Backup: Backing up data...
Cleanup: Cleaning up files...Exemplo de saída quando a entrada é 3:
Backup: Backing up data...
Cleanup: Cleaning up files...
Report: Generating report...A ideia central é que seu loop não precisa saber o que cada tarefa faz — ele simplesmente imprime o nome e chama run() em cada elemento. O mesmo código de iteração lida com todos os tipos de tarefas uniformemente. Lembre-se de usar include guards em seu arquivo de cabeçalho.
Folha de consulta
Você pode iterar por coleções de objetos que compartilham uma interface comum, chamando o mesmo ponteiro de função em cada elemento, independentemente de sua implementação específica. Isso é polimorfismo — tratar diferentes objetos de forma uniforme.
Defina um tipo de ponteiro de função e uma struct que o utilize:
typedef void (*ExecuteFunc)(void);
typedef struct {
const char* name;
ExecuteFunc execute;
} Action;Crie funções concretas que correspondam à assinatura:
void jump(void) { printf("Jumping!\n"); }
void run(void) { printf("Running!\n"); }
void rest(void) { printf("Resting...\n"); }Construa um array de structs, cada uma vinculada a uma função diferente, e então itere por elas:
Action actions[3] = {
{ "Jump", jump },
{ "Run", run },
{ "Rest", rest }
};
for (int i = 0; i < 3; i++) {
printf("%s: ", actions[i].name);
actions[i].execute();
}O loop não precisa saber o que cada ação faz internamente — ele simplesmente chama o ponteiro de função em cada elemento. Adicionar novos tipos não requer alterações na lógica de iteração.
Experimente você mesmo
#include <stdio.h>
#include "task.h"
// Declara as funções de tarefa implementadas em task.c
void backup_task(void);
void cleanup_task(void);
void report_task(void);
int main() {
int count;
scanf("%d", &count);
// TODO: Crie um array de 3 structs Task nesta ordem:
// 1. Tarefa de backup chamada "Backup" usando backup_task
// 2. Tarefa de limpeza chamada "Cleanup" usando cleanup_task
// 3. Tarefa de relatório chamada "Report" usando report_task
// TODO: Itere por 'count' tarefas do array
// Para cada tarefa, imprima: "<name>: " e então chame sua função run
return 0;
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Object Oriented Programming
1Fundamentos da Programação Modular
Arquivos de CabeçalhoInclude GuardsArquivos-FonteFunções EstáticasRecapitulação: Calculadora Modular4Encapsulamento
Conceito de Ponteiros OpacosDefinindo Structs OpacasGetters e SettersValidação em SettersRecapitulação: Caixa Secreta2Objetos e Métodos
Structs como ObjetosO Ponteiro 'Self'Const CorrectnessPonteiro vs ValorMétodos AuxiliaresRecapitulação: Point Manager5Projeto: Conta Bancária Simples
Configuração do ProjetoImplementação da Conta8Polimorfismo
Ponteiros de Função em StructsSimulando MétodosO Conceito de InterfaceImplementando InterfacesIteração PolimórficaRecapitulação: Greeter3Ciclo de Vida de Objetos
Padrão de ConstrutorPadrão de DestrutorInicialização na StackCópia ProfundaRecapitulação: String Wrapper6Herança via Composição
Incorporação de StructsA Regra do Primeiro MembroAcessando Membros PaiUpcastingRecapitulação: Hierarquia de Formas9Projeto: Desenhador de Formas
Visão Geral do ProjetoImplementação do Círculo