Simulando Métodos
Parte da seção Object Oriented Programming do Journey de C da Coddy — lição 39 de 61.
Você viu como colocar um ponteiro de função dentro de uma struct. O verdadeiro poder surge quando você atribui funções diferentes a instâncias diferentes do mesmo tipo de struct — é assim que simulamos métodos com comportamentos variados.
Considere uma struct que representa uma ação com lógica customizável:
typedef void (*ActionFunc)(void);
typedef struct {
const char* name;
ActionFunc execute;
} Action;Ao criar instâncias, você conecta funções diferentes a cada uma delas:
void say_hello(void) {
printf("Hello!\n");
}
void say_goodbye(void) {
printf("Goodbye!\n");
}
int main() {
Action greet = { "Greet", say_hello };
Action farewell = { "Farewell", say_goodbye };
greet.execute(); // Saída: Hello!
farewell.execute(); // Saída: Goodbye!
return 0;
}Tanto greet quanto farewell são do mesmo tipo (Action), mas chamar execute em cada um produz resultados completamente diferentes. A struct não apenas armazena dados — ela armazena comportamento que varia por instância.
Este padrão reflete como os objetos funcionam em outras linguagens: cada objeto pode ter sua própria implementação de um método, embora compartilhem a mesma interface.
Desafio
FácilVamos construir um sistema Speaker que demonstra como diferentes instâncias do mesmo tipo de struct podem exibir comportamentos completamente diferentes com base em qual função está conectada a elas.
Você criará dois arquivos para organizar seu código:
speaker.h: Defina um tipo de ponteiro de função chamadoSpeakFuncque não recebe parâmetros e não retorna nada. Em seguida, defina uma structSpeakercontendo umname(umconst char*) e um ponteiro de funçãospeakdo tipoSpeakFunc.main.c: Inclua seu cabeçalho e implemente três funções de fala diferentes:bark— imprimeWoof!meow— imprimeMeow!chirp— imprimeChirp!
Speaker, cada uma conectada a uma função diferente com base na entrada, e chame seus métodosspeakpara ver o comportamento polimórfico em ação.
Seu programa receberá duas entradas: o primeiro tipo de alto-falante (1 para bark, 2 para meow, 3 para chirp) e o segundo tipo de alto-falante (também 1, 2 ou 3).
Crie duas instâncias de Speaker — você pode nomeá-las como desejar (como "Dog", "Cat", "Bird", ou simplesmente "Speaker1", "Speaker2"). Conecte cada uma à função apropriada com base em seu código de entrada e, em seguida, chame speak em cada instância em ordem.
Exemplo de saída quando o primeiro tipo é 1 e o segundo tipo é 2:
Woof!
Meow!Exemplo de saída quando o primeiro tipo é 3 e o segundo tipo é 3:
Chirp!
Chirp!A ideia principal aqui é que ambos os alto-falantes são do mesmo tipo Speaker, mas produzem saídas diferentes porque cada um tem uma função diferente atribuída ao seu membro speak. Lembre-se de usar guards de inclusão em seu arquivo de cabeçalho.
Experimente você mesmo
#include <stdio.h>
#include "speaker.h"
// TODO: Implementar a função bark que imprime "Woof!"
// TODO: Implementar a função meow que imprime "Meow!"
// TODO: Implementar a função chirp que imprime "Chirp!"
int main() {
int type1, type2;
scanf("%d", &type1);
scanf("%d", &type2);
// TODO: Criar duas instâncias de Speaker
// TODO: Conectar a função speak do primeiro alto-falante com base em type1
// (1 = bark, 2 = meow, 3 = chirp)
// TODO: Conectar a função speak do segundo alto-falante com base em type2
// (1 = bark, 2 = meow, 3 = chirp)
// TODO: Chamar speak em cada alto-falante em ordem
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írculoImplementação do RetânguloUso PolimórficoContainer de Formas