Как сохранить ваш код чистым с помощью инкапсуляции объектов
Инкапсуляция означает изоляцию чего-либо. Если вы поместите что-то в капсулу, внешний мир не сможет получить к ней доступ. Инкапсуляция – важная концепция объектно-ориентированного программирования, поскольку она помогает поддерживать управляемость сложного кода.
Зачем нужны занятия
Допустим, у вас есть приложение "детский зоопарк" с сотнями тысяч строк кода. Теперь представьте, что есть очень важный объект, который является центральным для всего приложения, под названием 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 о том, как создавать классовые / статические переменные, чтобы узнать, как это сделать.