Simulando métodos
Parte da seção Programação Orientada a Objetos do Journey de C da Coddy. Lição 39 de 61.
Você viu como colocar um ponteiro para função dentro de uma struct. O verdadeiro poder aparece 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 estrutura que representa uma ação com lógica personalizá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:
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 deles produz resultados completamente diferentes. A struct não apenas armazena dados. Ela armazena comportamentos que variam de uma instância para outra.
Esse padrão reflete o funcionamento dos objetos em outras linguagens: cada objeto pode ter sua própria implementação de um método, mesmo que compartilhem a mesma interface.
Desafio
FácilVamos criar um sistema Speaker que demonstra como instâncias diferentes do mesmo tipo de struct podem apresentar comportamentos completamente distintos, dependendo de qual função é associada a elas.
Você criará dois arquivos para organizar seu código:
speaker.h: Defina um tipo de ponteiro para função chamadoSpeakFuncque não recebe parâmetros e não retorna nada. Em seguida, defina uma structSpeakerque contenha umname(umconst char*) e um ponteiro para funçãospeakdo tipoSpeakFunc.main.c: Inclua seu cabeçalho e implemente três funções diferentes de fala:bark: imprimeWoof!meow: imprimeMeow!chirp: imprimeChirp!
Speaker, cada uma associada a uma função diferente com base na entrada, e chame as funçõesspeakdelas para ver o comportamento polimórfico em ação.
Seu programa receberá duas entradas: o tipo do primeiro alto-falante (1 para bark, 2 para meow, 3 para chirp) e o tipo do segundo alto-falante (também 1, 2 ou 3).
Crie duas instâncias de Speaker. Você pode dar a elas os nomes que quiser (como "Dog", "Cat", "Bird" ou simplesmente "Speaker1", "Speaker2"). Associe cada uma à função apropriada com base no código de entrada e, em seguida, chame speak em cada instância, na 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 os dois 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 guardas de inclusão no arquivo de cabeçalho.
Experimente você mesmo
#include <stdio.h>
#include "speaker.h"
// TODO: Implemente a função bark que imprime "Woof!"
// TODO: Implemente a função meow que imprime "Meow!"
// TODO: Implemente a função chirp que imprime "Chirp!"
int main() {
int type1, type2;
scanf("%d", &type1);
scanf("%d", &type2);
// TODO: Crie duas instâncias de Speaker
// TODO: Configure a função speak do primeiro speaker com base em type1
// (1 = bark, 2 = meow, 3 = chirp)
// TODO: Configure a função speak do segundo speaker com base em type2
// (1 = bark, 2 = meow, 3 = chirp)
// TODO: Chame speak em cada speaker na 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 Programação Orientada a Objetos
1Fundamentos da Programação Modular
Arquivos de cabeçalhoProteções de inclusãoArquivos-fonteFunções estáticasRevisão: calculadora modular4Encapsulamento
Conceito de ponteiros opacosDefinindo structs opacasGetters e settersValidação em settersRevisão: caixa secreta2Objetos e métodos
Structs como objetosO ponteiro 'Self'Correção de constPonteiro vs. valorMétodos auxiliaresRevisão: Gerenciador de pontos5Projeto: Conta Bancária Simples
Configuração do ProjetoImplementação da Conta8Polimorfismo
Ponteiros para funções em structsSimulando métodosO conceito de interfaceImplementando interfacesIteração polimórficaRevisão: Greeter3Ciclo de vida do objeto
Padrão de construtorPadrão de destrutorInicialização da pilhaCópia profundaRevisão: wrapper de String6Herança por composição
Incorporação de structRegra do primeiro membroAcessando membros do tipo paiUpcastingRevisão: hierarquia de formas9Projeto: Desenhador de Formas
Visão geral do projetoImplementação do círculoImplementação do retânguloUso polimórficoContêiner de formasPratique por conta própria: Compilador de C online