Как сохранить ваш код чистым с помощью инкапсуляции объектов

Инкапсуляция означает изоляцию чего-либо. Если вы поместите что-то в капсулу, внешний мир не сможет получить к ней доступ. Инкапсуляция – важная концепция объектно-ориентированного программирования, поскольку она помогает поддерживать управляемость сложного кода.

Зачем нужны занятия

Допустим, у вас есть приложение "детский зоопарк" с сотнями тысяч строк кода. Теперь представьте, что есть очень важный объект, который является центральным для всего приложения, под названием animal . Что, если бы каждая отдельная часть программы, которая была животным, могла получить доступ к этому объекту и изменить его?

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

В JavaScript / TypeScript это будет выглядеть так:

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

Следующее, что вы знаете, это розовые козы и поросята с рогами. Посмотрите, как работает код в песочнице TypeScript, затем нажмите « Выполнить», чтобы просмотреть вывод консоли.

Если вы учитесь программировать и хотите вдохновения помимо создания контактного зоопарка, вот еще 10 проектов, которые могут вас вдохновить .

Поскольку ваша кодовая база настолько огромна, на поиск кода, который дает вашим ягнятам шею ламы и шерсть утят, могут потребоваться сотни часов. И как только вы найдете проблемный код, вам придется написать еще больше спагетти-кода, чтобы объекты не мешали друг другу. Должен быть способ получше.

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

Классов мало; Ваши объектные переменные тоже нуждаются в инкапсуляции

Итак, мы решили, что каждому животному нужен свой объект. Давайте создадим класс, который будет определять наших животных.

 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.color = "black";
bunny.legs = 8;

Кролики-пауки – это не круто, мужик! Это так же плохо, как если бы мы не инкапсулировали наш код в объекты. Давайте сделаем так, чтобы этого больше никогда не повторилось.

Первое, что нам нужно сделать, это сделать наши объекты приватными . Это означает, что ничто не может редактировать наши переменные сразу после их создания. Вот код, показывающий, что изменение частных переменных вызывает ошибку .

Однако переменные должны быть изменяемыми. И вот тут-то и пригодятся геттеры и сеттеры .

Геттеры и сеттеры – это функции, которые контролируют доступ и изменяют переменные. Сеттеры могут устанавливать ограничения на изменяемые данные. А геттеры могут изменять получаемые данные.

Вот как выглядит наш класс с функциями get и set для управления количеством ног.

 class Animal {
private _name: string;
private _legs: number;
private _color: string;
private _decoration: string;
constructor(name: string, legs: number, color: string, decoration: string) {
this._name = name;
this._legs = legs;
this._color = color;
this._decoration = decoration;
}
get legs() {
return this._legs;
}
set legs(legCount: number) {
if(legCount > 1 && legCount < 5) {
this._legs = legCount;
}
}
}

Изучите инкапсуляцию и избегайте глобальных переменных

Вот последний код. Обобщите то, что вы узнали, чтобы обеспечить понимание:

  • Добавьте геттеры и сеттеры для остальных переменных.
  • Верните имя животного в виде тега span: <span> llama </span>
  • Измените переменную декора, чтобы разрешить несколько украшений. Создайте подходящие методы получения и установки, чтобы отразить это изменение.

Если вы хотите, чтобы ваш код работал как хорошо отлаженная машина, вам абсолютно необходимо использовать инкапсуляцию. Любой ценой избегайте глобальных переменных. А если вам действительно нужно разделять переменные между объектами, вы можете просмотреть документацию TypeScript о том, как создавать классовые / статические переменные, чтобы узнать, как это сделать.