Menu
Coddy logo textTech

Концепция интерфейсов

Часть раздела Объектно-ориентированное программирование путешествия по C на Coddy. Урок 40 из 61.

До сих пор наши структуры объединяли данные и поведение: например, имя вместе с указателем на функцию. Но что, если структура содержала бы только указатели на функции? Это создаёт нечто мощное: interface.

Интерфейс определяет какие операции доступны, не уточняя, как они работают. Это контракт, в котором говорится: «любой объект, реализующий этот интерфейс, должен предоставлять эти functions».

typedef void (*LogFunc)(const char* message);

typedef struct {
    LogFunc log;
} ILogger;

Структура ILogger содержит только указатель на function. У неё нет собственных данных. Она исключительно описывает поведение. Префикс «I» — это распространённое соглашение, указывающее, что это interface.

Любой код, принимающий ILogger, не заботится о том, куда попадает сообщение журнала. Оно может выводиться в консоль, записываться в файл или отправляться по сети. Вызывающий код лишь знает, что может вызвать log:

void process(ILogger* logger, const char* msg) {
    logger->log(msg);  // Мы не знаем, КАК он логирует
}

Это разделение — сущность полиморфизма. Функция process работает с любой реализацией logger. Можно менять поведение, не изменяя код функции. На следующем уроке ты создашь конкретные реализации, которые выполняют условия этого контракта interface.

challenge icon

Задание

Легко

Давайте создадим интерфейс ICalculator: структуру, содержащую только указатели на functions и определяющую, какие операции должен поддерживать любой калькулятор, не указывая, как именно они работают.

Вы создадите два файла, чтобы организовать свой код:

  • calculator.h: определите интерфейс здесь. Создайте тип указателя на function с именем BinaryOp, который принимает два параметра типа int и возвращает int. Затем определите структуру ICalculator, содержащую только два указателя на functions: operate (типа BinaryOp) и describe (указатель на function, которая не принимает параметров и ничего не возвращает). Эта структура является исключительно интерфейсом. Она не содержит данных, только поведение.
  • main.c: подключите заголовочный файл и реализуйте конкретные functions, которые могут соответствовать интерфейсу:
    • add: возвращает сумму двух integers
    • multiply: возвращает product двух integers
    • describe_add: выводит Addition
    • describe_multiply: выводит Multiplication
    Затем создайте экземпляр ICalculator, настройте его на основе входных данных и используйте его для выполнения вычисления.

Ваша программа получит три входных значения: два integers и код операции (1 для сложения, 2 для умножения).

В зависимости от кода операции свяжите ICalculator с соответствующей парой functions. Затем вызовите describe через интерфейс, чтобы вывести название операции, после чего вызовите operate, чтобы вычислить и вывести result.

Пример вывода, если входные данные — 5, 3 и 1:

Addition
8

Пример вывода, если входные данные — 4, 7 и 2:

Multiplication
28

Главная идея заключается в том, что структура ICalculator определяет контракт: любой код, использующий её, know, что может вызвать describe и operate, не зная, какие именно functions подключены. Не забудьте использовать защиту от повторного включения в заголовочном файле.

Попробуйте сами

#include <stdio.h>
#include "calculator.h"

// TODO: Реализуйте функцию add
// Возвращает сумму двух целых чисел


// TODO: Реализуйте функцию multiply
// Возвращает произведение двух целых чисел


// TODO: Реализуйте функцию describe_add
// Выводит "Addition"


// TODO: Реализуйте функцию describe_multiply
// Prints "Multiplication"


int main() {
    int num1, num2, op_code;
    scanf("%d", &num1);
    scanf("%d", &num2);
    scanf("%d", &op_code);
    
    // TODO: Создайте экземпляр ICalculator
    
    
    // TODO: На основе op_code (1 для add, 2 для multiply),
    // свяжите калькулятор с соответствующими функциями
    
    
    // TODO: Вызовите describe через интерфейс
    
    
    // TODO: Вызовите operate через интерфейс и выведите результат
    
    
    return 0;
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор C