O conceito de interface
Parte da seção Programação Orientada a Objetos do Journey de C da Coddy. Lição 40 de 61.
Até agora, nossas structs combinaram dados e comportamento: por exemplo, um nome junto com um ponteiro para função. Mas e se uma struct contivesse apenas ponteiros para função? Isso cria algo poderoso: uma interface.
Uma interface define quais operações estão disponíveis sem especificar como elas funcionam. É um contrato que diz: "qualquer objeto que implemente essa interface deve fornecer estas funções."
typedef void (*LogFunc)(const char* message);
typedef struct {
LogFunc log;
} ILogger;A estrutura ILogger contém apenas um ponteiro para função. Ela não possui dados próprios. Ela descreve apenas comportamento. O prefixo "I" é uma convenção comum que indica que se trata de uma interface.
Qualquer código que aceita um ILogger não se importa para onde a mensagem de log vai. Ela pode ser impressa no console, gravada em um arquivo ou enviada pela rede. Quem faz a chamada só sabe que pode chamar log:
void process(ILogger* logger, const char* msg) {
logger->log(msg); // Não sabemos COMO ele registra a mensagem
}Essa separação é a essência do polimorfismo. A função process funciona com qualquer implementação de registrador. Você pode trocar os comportamentos sem alterar o código da função. Na próxima lição, você criará implementações concretas que cumprem este contrato de interface.
Desafio
FácilVamos criar uma interface ICalculator: uma struct que contém apenas ponteiros para funções, definindo quais operações qualquer calculadora deve oferecer sem especificar como elas funcionam.
Você criará dois arquivos para organizar seu código:
calculator.h: Defina sua interface aqui. Crie um tipo de ponteiro para função chamadoBinaryOpque recebe dois parâmetrosinte retorna umint. Em seguida, defina uma structICalculatorque contém apenas dois ponteiros para funções:operate(do tipoBinaryOp) edescribe(um ponteiro para função que não recebe parâmetros e não retorna nada). Essa struct é puramente uma interface. Ela não contém dados, apenas comportamento.main.c: Inclua seu cabeçalho e implemente funções concretas que atendam à interface:add: retorna a soma de dois inteirosmultiply: retorna o produto de dois inteirosdescribe_add: imprimeAdditiondescribe_multiply: imprimeMultiplication
ICalculator, configure-a com base na entrada e use-a para realizar um cálculo.
Seu programa receberá três entradas: dois inteiros e um código de operação (1 para adição, 2 para multiplicação).
Com base no código de operação, configure seu ICalculator com o par de funções apropriado. Em seguida, chame describe pela interface para imprimir o nome da operação e, depois, chame operate para calcular e imprimir o resultado.
Exemplo de saída quando as entradas são 5, 3 e 1:
Addition
8Exemplo de saída quando as entradas são 4, 7 e 2:
Multiplication
28A ideia principal é que sua struct ICalculator define um contrato: qualquer código que a use sabe que pode chamar describe e operate, sem saber quais funções específicas estão configuradas. Lembre-se de usar guardas de inclusão no seu arquivo de cabeçalho.
Experimente você mesmo
#include <stdio.h>
#include "calculator.h"
// TODO: Implemente a função add
// Retorna a soma de dois números inteiros
// TODO: Implemente a função multiply
// Retorna o produto de dois números inteiros
// TODO: Implemente a função describe_add
// Imprime "Addition"
// TODO: Implemente a função describe_multiply
// Imprime "Multiplication"
int main() {
int num1, num2, op_code;
scanf("%d", &num1);
scanf("%d", &num2);
scanf("%d", &op_code);
// TODO: Crie uma instância de ICalculator
// TODO: Com base em op_code (1 para add, 2 para multiply),
// configure a calculadora com as funções apropriadas
// TODO: Chame describe por meio da interface
// TODO: Chame operate por meio da interface e imprima o resultado
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