Menu
CoddyTech

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.

challenge icon

Desafio

Fácil

Vamos 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 chamado SpeakFunc que não recebe parâmetros e não retorna nada. Em seguida, defina uma struct Speaker que contenha um name (um const char*) e um ponteiro para função speak do tipo SpeakFunc.
  • main.c: Inclua seu cabeçalho e implemente três funções diferentes de fala:
    • bark: imprime Woof!
    • meow: imprime Meow!
    • chirp: imprime Chirp!
    Em seguida, crie duas instâncias de Speaker, cada uma associada a uma função diferente com base na entrada, e chame as funções speak delas 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;
}
quiz iconTeste seus conhecimentos

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

Pratique por conta própria: Compilador de C online