Гид по технологиям

Инкапсуляция в TypeScript: классы, геттеры и сеттеры

4 min read Программирование Обновлено 29 Dec 2025
Инкапсуляция в TypeScript: геттеры и сеттеры
Инкапсуляция в TypeScript: геттеры и сеттеры

красная и синяя капсула на синем фоне

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

Что такое инкапсуляция (одно предложение)

Инкапсуляция — это практика скрывать внутренние данные и предоставлять контролируемый интерфейс для их чтения и изменения.

Почему нужны классы

Представьте приложение «контактный зоопарк» с сотнями тысяч строк кода. Есть центральный объект animal. Что произойдет, если любой кусок программы сможет напрямую менять поля animal?

Бесконтрольный доступ приведет к хаосу. Если поросёнок назначит параметры animal, то у объекта появятся поля поросёнка. Если затем коза тоже изменит animal, вы получите странные смешения: розовые козы и поросята с рогами.

Вот аналогичная ситуация в JS/TS (упрощённо):

var animal = { name: 'piglet', legs: 4, color: 'pink', decoration: 'snout' };
animal.name = 'goat';
animal.decoration = 'horns';

Если код большой, поиск и исправление всех мест, где кто-то мутирует общие объекты, займёт часы и добавит ещё больше «спагетти»-кода для обхода проблем. Лучшее решение — определять объекты через классы и создавать экземпляры (instantiation). Каждый экземпляр получает собственные свойства и не мешает другим.

Классы — это не всё: поля объектов тоже нужно инкапсулировать

Создадим класс Animal в TypeScript, который задаёт структуру сущности:

class Animal {
  name: string;
  legs: number;
  color: string;
  decoration: string;

  constructor(name: string, legs: number, color: string, decoration: string) {
    this.name = name;
    this.legs = legs;
    this.color = color;
    this.decoration = decoration;
  }
}

let babyDuck = new Animal('baby duck', 2, 'yellow', 'beak');
let bunny = new Animal('bunny', 4, 'gray', 'floppy ears');

Пока всё хорошо — каждый объект отдельный. Но что если уставший программист по ошибке поменял объект bunny?

bunny.color = 'black';
bunny.legs = 8; // оops

Кролики‑пауки — нежелательный эффект. Чтобы этого избежать, поля класса нужно сделать приватными и управлять доступом через геттеры и сеттеры.

серо-белый кролик на травянистом поле

Приватные поля и контролируемый доступ

В TypeScript приватные поля обозначают ключевым словом private. Вместо прямого доступа даём публичные геттеры/сеттеры с валидацией:

class Animal {
  private _name: string;
  private _legs: number;
  private _color: string;
  private _decoration: string | string[];

  constructor(name: string, legs: number, color: string, decoration: string | string[]) {
    this._name = name;
    this._legs = legs;
    this._color = color;
    this._decoration = decoration;
  }

  get legs() {
    return this._legs;
  }

  set legs(legCount: number) {
    if (legCount > 0 && legCount <= 8) {
      this._legs = legCount;
    } else {
      // проигнорировать некорректное значение или бросить ошибку
    }
  }

  get name() {
    return this._name;
  }

  set name(value: string) {
    if (value && value.length < 50) {
      this._name = value;
    }
  }

  get color() {
    return this._color;
  }

  set color(value: string) {
    // можно нормализовать цвет: lowerCase, валидация и т.д.
    this._color = value;
  }

  get decoration() {
    return Array.isArray(this._decoration) ? this._decoration.slice() : [this._decoration];
  }

  set decoration(value: string | string[]) {
    if (typeof value === 'string') {
      this._decoration = [value];
    } else {
      this._decoration = value;
    }
  }
}

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

  • Приватные поля защищают внутреннее состояние.
  • Геттеры возвращают безопасную копию (slice) для массивов, чтобы внешний код не мутировал внутренние структуры.
  • Сеттеры выполняют валидацию и нормализацию.

Практические советы и шаблон действий (mini‑методология)

  1. Начните с определения минимально необходимого публичного API класса.
  2. Сделайте все внутренние поля приватными.
  3. Добавьте геттеры/сеттеры только для тех полей, которые должны быть доступны извне.
  4. В сеттерах выполняйте валидацию и нормализацию данных.
  5. Для коллекций возвращайте копии вместо прямых ссылок.
  6. Используйте static поля только для данных, общих для всех экземпляров.
  7. Покройте поведение тестами: граничные и ошибочные значения.

Когда инкапсуляция может не быть оптимальной (контрпримеры)

  • Небольшие скрипты или прототипы, где overhead от классов мешает простоте. В таком случае простые функции и объекты могут быть приемлемы.
  • Высокопроизводительный код, где создание копий массивов в геттерах становится узким местом. Тогда нужно документировать ограничения и предоставлять методы-операции, а не копии.

Альтернативы и дополнения

  • Функциональный подход: неизменяемые объекты и pure-функции вместо геттеров/сеттеров.
  • Компонентный подход (например, ECS) для игр, где данные и поведение отделены.
  • Использование TypeScript readonly для обеспечения неизменности после создания.

Ролевые чек‑листы при ревью кода

Для разработчика:

  • Приватны ли поля, не предназначенные для внешнего доступа?
  • Есть ли валидация в сеттерах?
  • Возвращаются ли копии коллекций?

Для ревьюера:

  • Нет ли прямых мутаций объектов из других модулей?
  • Хорошо ли покрыты тестами граничные случаи?

Для архитектора:

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

Примеры использования статических/классных переменных

Если нужно разделять данные между всеми экземплярами класса, используйте static:

class Zoo {
  static totalAnimals = 0;

  constructor() {
    Zoo.totalAnimals += 1;
  }
}

Но помните: static — это глобальное состояние в масштабе класса. Его нужно документировать и ограничивать.

Ментальные модели и эвристики

  • Подумайте о каждом объекте как об отдельном «ящике» с крышкой: кто может её открыть и как.
  • Правило трёх: если поле требует контроля доступа в трёх местах кода — сделайте его приватным и вынесите проверку в метод или сеттер.

Критерии приёмки

  • Все внутренние поля, не предназначенные для публичного API, объявлены private.
  • Сеттеры выполняют базовую валидацию и не допускают «нелогичных» состояний.
  • Тесты проверяют корректные и некорректные значения для сеттеров и геттеров.

Тестовые случаи (основные)

  • Попытка установить legs = -1 должна быть проигнорирована или вызвать ошибку.
  • Установка decoration строкой и массивом должна приводить к корректному внутреннему виду.
  • Геттер decoration должен возвращать копию массива: изменение результата не должно менять внутреннее поле.

Краткое резюме

  • Инкапсуляция предотвращает нежелательные мутации и уменьшает связность.
  • Используйте private поля и геттеры/сеттеры для контроля доступа и валидации.
  • Возвращайте копии коллекций и документируйте static-поля.

Важно: инкапсуляция не панацея. Она снижает риск ошибок, но требует дисциплины и хорошего тестирования.

Часто задаваемые вопросы

Что такое геттер и сеттер?

Геттер — это метод, который возвращает значение поля; сеттер — метод, который изменяет поле с возможной валидацией.

Нужно ли всегда использовать геттеры/сеттеры?

Нет. Для простых DTO или immutable-объектов геттеры/сеттеры не всегда нужны. Для сущностей с бизнес-логикой они практически обязательны.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Отключить фоновые приложения в Windows 11
Windows

Отключить фоновые приложения в Windows 11

Совместная работа в VS Code с Live Share
Development

Совместная работа в VS Code с Live Share

Как вставить и найти символы в Google Docs
Руководство

Как вставить и найти символы в Google Docs

Google Play Music Desktop Player — обзор клиента
Обзоры

Google Play Music Desktop Player — обзор клиента

Как поставить GIF в фон Google
Персонализация

Как поставить GIF в фон Google

Запись экрана с аудио в Snipping Tool — Windows 11
Windows

Запись экрана с аудио в Snipping Tool — Windows 11