Menu
Coddy logo textTech

Геттеры и сеттеры

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

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

class Temperature {
    double celsius;    // Приватное поле - нельзя получить доступ напрямую
    
public:
    // Геттер - возвращает значение
    double getCelsius() const {
        return celsius;
    }
    
    // Сеттер - изменяет значение с проверкой
    void setCelsius(double value) {
        if (value >= -273.15) {    // Проверка на абсолютный ноль
            celsius = value;
        }
    }
};

Настоящая сила сеттеров заключается в валидации.

Вместо того чтобы разрешать присваивание любого значения, вы можете устанавливать правила. В примере выше значения температуры ниже абсолютного нуля отклоняются. Без сеттера любой мог бы напрямую присвоить некорректные данные.

Геттеры также могут преобразовывать данные перед их возвратом:

class Temperature {
    double celsius;
public:
    double getCelsius() const { return celsius; }
    
    // Вычисляемый геттер — не хранит значение в фаренгейтах, а вычисляет его
    double getFahrenheit() const {
        return celsius * 9.0 / 5.0 + 32.0;
    }
    
    void setCelsius(double value) { celsius = value; }
};

Обратите внимание на ключевое слово const в геттерах — это указывает на то, что они не изменяют объект. Сеттеры не могут быть const, так как их цель — изменять значения членов класса. Этот паттерн использования геттеров и сеттеров является основополагающим для инкапсуляции, предоставляя вам полный контроль над тем, как осуществляется доступ к данным вашего класса и их изменение.

challenge icon

Задание

Легко

Давайте создадим систему профилей игроков, которая демонстрирует, как геттеры и сеттеры обеспечивают контролируемый доступ к приватным данным, включая валидацию и вычисляемые свойства.

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

  • Player.h: Определите класс Player, который управляет профилем игрового персонажа с защищенным доступом к данным. Ваш класс должен иметь:
    • Приватные члены: name (string), level (int) и experience (int)
    • Конструктор, который принимает имя и инициализирует level значением 1, а experience значением 0
    • Геттер getName(), который возвращает имя игрока
    • Геттер getLevel(), который возвращает текущий уровень
    • Геттер getExperience(), который возвращает текущие очки опыта
    • Сеттер setName(), который принимает только имена длиной не менее 3 символов — если имя невалидно, оставьте текущее имя без изменений
    • Сеттер addExperience(int points), который принимает только положительные значения. Когда опыт достигает или превышает 100, уровень игрока повышается: увеличьте уровень на 1 и вычтите 100 из опыта. Это может произойти несколько раз, если добавлено достаточно опыта.
    • Вычисляемый геттер getExperienceToNextLevel(), который возвращает количество очков опыта, необходимых для достижения следующего уровня (всегда 100 - current experience)

    Пометьте все геттеры как const, так как они не изменяют объект.

  • main.cpp: Продемонстрируйте работу ваших геттеров и сеттеров. Считайте имя игрока и очки опыта для добавления из входных данных (каждое на отдельной строке), затем:
    • Создайте объект Player с введенным именем
    • Выведите "Player: <name>, Level: <level>, XP: <experience>"
    • Добавьте введенные очки опыта с помощью addExperience()
    • Снова выведите ту же строку состояния, чтобы показать обновленное состояние
    • Выведите "XP to next level: <amount>"
    • Попробуйте изменить имя на "Al" (валидация должна не пройти)
    • Выведите "Name after invalid change: <name>"
    • Измените имя на "Champion" (должно пройти успешно)
    • Выведите "Name after valid change: <name>"

Ввод опыта будет предоставлен в виде строки, которую вам нужно будет преобразовать в целое число. Подключите ваш заголовочный файл в main.cpp с помощью #include "Player.h".

Шпаргалка

Геттеры и сеттеры — это публичные методы, которые обеспечивают контролируемый доступ к приватным членам класса.

Базовый паттерн геттера и сеттера:

class Temperature {
    double celsius;    // Приватный член
    
public:
    // Геттер - возвращает значение (помечен как const)
    double getCelsius() const {
        return celsius;
    }
    
    // Сеттер - изменяет значение
    void setCelsius(double value) {
        celsius = value;
    }
};

Сеттеры с валидацией:

void setCelsius(double value) {
    if (value >= -273.15) {    // Валидация перед установкой
        celsius = value;
    }
}

Вычисляемые геттеры:

// Возвращает вычисленное значение без его сохранения
double getFahrenheit() const {
    return celsius * 9.0 / 5.0 + 32.0;
}

Ключевые моменты:

  • Геттеры должны быть помечены как const, так как они не изменяют объект
  • Сеттеры не могут быть const, так как они изменяют значения членов
  • Сеттеры позволяют выполнять валидацию для предотвращения некорректных данных
  • Геттеры могут преобразовывать или вычислять значения перед их возвратом

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

#include <iostream>
#include <string>
#include "Player.h"

using namespace std;

int main() {
    // Считать имя игрока
    string playerName;
    getline(cin, playerName);

    // Считать очки опыта для добавления (как строку, преобразовать в int)
    string expString;
    getline(cin, expString);
    int expToAdd = stoi(expString);

    // TODO: Создать объект Player с введенным именем

    // TODO: Вывести начальный статус: "Player: <name>, Level: <level>, XP: <experience>"

    // TODO: Добавить введенные очки опыта, используя addExperience()

    // TODO: Вывести обновленную строку статуса

    // TODO: Вывести "XP to next level: <amount>"

    // TODO: Попробовать изменить имя на "Al" (валидация должна не пройти)

    // TODO: Вывести "Name after invalid change: <name>"

    // TODO: Изменить имя на "Champion" (должно пройти успешно)

    // TODO: Вывести "Name after valid change: <name>"

    return 0;
}
quiz iconПроверьте себя

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

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