Инкапсуляция и контроль состояния
Смысл инкапсуляции
Инкапсуляция скрывает внутреннюю реализацию и предоставляет операции, через которые объект можно использовать корректно. Поля часто делают private, чтобы внешний код не мог произвольно нарушить правила.
class Health {public: explicit Health(int maximum) : maximum(maximum), current(maximum) {} void Damage(int amount) { if (amount <= 0) return; current = amount >= current ? 0 : current - amount; } int Current() const { return current; } int Maximum() const { return maximum; }private: int maximum; int current;};Так класс контролирует, чтобы здоровье не становилось отрицательным из-за внешнего присваивания.
Инварианты
Инвариант — условие, которое должно быть истинным для корректного объекта. Например, current >= 0 и current <= maximum. Конструктор должен устанавливать корректное состояние, а публичные методы — сохранять его.
Геттеры и сеттеры
Геттер читает значение, сеттер меняет его. Не обязательно создавать сеттер для каждого поля: если изменение не должно быть произвольным, лучше предоставить осмысленную операцию (Damage, Heal, Rename) вместо SetEverything.
Модификаторы доступа
public— часть интерфейса, доступная пользователям класса.private— внутренняя реализация.protected— доступен самому классу и производным классам; применять его следует осознанно.
Композиция
Часто класс проще построить из других объектов, чем наследовать от них. Например, Car может содержать объект Engine, а не наследоваться от Engine: это отражает отношение «имеет», а не «является».
Итог
Делай некорректное состояние труднодостижимым. Хороший интерфейс предоставляет действия, отражающие смысл предметной области, а не только прямой доступ ко всем полям.
