Menu
Coddy logo textTech

Сокрытие данных

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

Скрытие информации выходит за рамки простого использования спецификаторов доступа. Это принцип проектирования, при котором вы скрываете не только данные, но и детали реализации того, как ваш класс работает внутри.

Цель состоит в том, чтобы предоставить пользователям вашего класса только то, что им необходимо знать, скрывая все остальное. Это позволяет изменять внутреннюю реализацию, не затрагивая код, который использует ваш класс:

class Temperature {
    double kelvin;    // Внутреннее представление — скрытая деталь
    
public:
    void setCelsius(double c) {
        kelvin = c + 273.15;    // Преобразование скрыто от пользователя
    }
    
    double getCelsius() const {
        return kelvin - 273.15;
    }
    
    double getFahrenheit() const {
        return (kelvin - 273.15) * 9.0/5.0 + 32;
    }
};

Пользователи этого класса не знают (и им не нужно знать), что температура хранится внутри в Кельвинах. Если позже вы решите хранить её в Цельсиях, вы измените только внутреннюю реализацию — публичный интерфейс останется неизменным.

Это разделение между интерфейсом и реализацией дает несколько преимуществ: оно снижает сложность для пользователей вашего класса, предотвращает случайное неправильное использование внутренних данных и делает ваш код более простым в обслуживании. Когда внутренние детали скрыты, вы можете свободно оптимизировать или проводить рефакторинг, не нарушая работу существующего кода, который зависит от вашего класса.

challenge icon

Задание

Легко

Давайте создадим класс Distance, который демонстрирует сокрытие информации, сохраняя расстояния внутри в сантиметрах, предоставляя при этом чистый интерфейс для работы с различными единицами измерения. Пользователям вашего класса не нужно будет знать (или беспокоиться) о том, как расстояние хранится внутри — они просто будут работать с той единицей измерения, которая им удобна.

Для организации кода вы создадите два файла:

  • Distance.h: Определите класс Distance, который скрывает свое внутреннее представление, предоставляя гибкий публичный интерфейс. Внутри храните расстояние в сантиметрах (в виде double) — это ваша скрытая деталь реализации. Ваш публичный интерфейс должен позволять пользователям:
    • Устанавливать расстояние с помощью setMeters(double m), setCentimeters(double cm) или setKilometers(double km)
    • Получать расстояние с помощью getMeters(), getCentimeters() или getKilometers() — все они должны быть методами const
    • Складывать два расстояния с помощью add(const Distance& other), который возвращает новый объект Distance

    Включите конструктор по умолчанию, который инициализирует расстояние нулем. Логика преобразования должна быть скрыта внутри ваших методов — пользователи просто вызывают setKilometers(5) и getMeters(), не беспокоясь о внутреннем формате хранения.

  • main.cpp: Продемонстрируйте, что пользователи могут работать с вашим классом, не зная внутреннего представления. Считайте два значения расстояния из входных данных: первое в метрах, второе в километрах. Затем:
    • Создайте объект Distance и установите его значение, используя метры
    • Выведите "In meters: <value> m"
    • Выведите "In centimeters: <value> cm"
    • Выведите "In kilometers: <value> km"
    • Создайте второй объект Distance и установите его значение, используя километры
    • Сложите два расстояния и сохраните результат
    • Выведите "Combined in meters: <value> m"

Прелесть сокрытия информации заключается в том, что позже вы сможете изменить внутреннее хранилище с сантиметров на миллиметры (или на что-то другое), не меняя того, как пользователи взаимодействуют с вашим классом. Публичный интерфейс остается стабильным, даже если реализация меняется.

Форматируйте все выходные значения с двумя знаками после запятой, используя std::fixed и std::setprecision(2) из <iomanip>. Преобразуйте входные строки в числа с плавающей точкой с помощью std::stod().

Справочник по преобразованию: 1 метр = 100 сантиметров, 1 километр = 1000 метров.

Шпаргалка

Скрытие информации — это принцип проектирования, при котором вы скрываете детали реализации того, как ваш класс работает внутри, предоставляя только то, что пользователям необходимо знать.

Это позволяет изменять внутреннюю реализацию, не затрагивая код, использующий ваш класс:

class Temperature {
    double kelvin;    // Внутреннее представление — скрытая деталь
    
public:
    void setCelsius(double c) {
        kelvin = c + 273.15;    // Преобразование скрыто от пользователя
    }
    
    double getCelsius() const {
        return kelvin - 273.15;
    }
    
    double getFahrenheit() const {
        return (kelvin - 273.15) * 9.0/5.0 + 32;
    }
};

Пользователи не знают (и им не нужно знать), что температура хранится внутри в Кельвинах. Если вы позже измените формат хранения, изменится только приватная реализация — публичный интерфейс останется прежним.

Преимущества скрытия информации:

  • Снижает сложность для пользователей вашего класса
  • Предотвращает случайное неправильное использование внутренних данных
  • Упрощает поддержку и рефакторинг кода
  • Позволяет проводить оптимизацию, не ломая существующий код

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

#include <iostream>
#include <string>
#include <iomanip>
#include "Distance.h"

using namespace std;

int main() {
    // Считать входные значения
    string metersInput, kmInput;
    cin >> metersInput;  // Первое значение в метрах
    cin >> kmInput;      // Второе значение в километрах
    
    // Преобразовать строки в double с помощью `std::stod()`
    double metersValue = stod(metersInput);
    double kmValue = stod(kmInput);
    
    // Установить форматирование вывода
    cout << fixed << setprecision(2);
    
    // TODO: Создать первый объект Distance и установить его, используя значение в метрах
    
    // TODO: Вывести "In meters: <value> m"
    
    // TODO: Вывести "In centimeters: <value> cm"
    
    // TODO: Вывести "In kilometers: <value> km"
    
    // TODO: Создать второй объект Distance и установить его, используя значение в километрах
    
    // TODO: Сложить две дистанции вместе, используя метод `add()`
    
    // TODO: Вывести "Combined in meters: <value> m"
    
    return 0;
}
quiz iconПроверьте себя

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

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