Прототипное наследование

Давайте немного об ООП

ООП - это о том, что мы теперь будет оперировать в своей программе не только функциями, какими-либо данными в переменных и.т.п, а постараемся выражать логику в объектах которые будут инкапсулировать в себе данные и методы для работы с этими данными.

note

Советую почитать вам эту статью, которая должна расставить некоторые вещи в ваших головах.

Давайте с ходу начнем с примера кода, в котором у нас есть информация о пользователе внутри объекта и мы хотим отправить сообщение этому пользователю:

const valid_user = {
first_name: "John",
last_name: "Dow",
email: "john@mail.ru",
sended_emails_count: null,
};
const invalid_user = {
first_name: "John",
last_name: "Dow",
email: "john.ru",
sended_emails_count: null,
};

Инкап­су­ля­ция

Инкап­су­ля­ция — объ­ект неза­ви­сим: каж­дый объ­ект устро­ен так, что нуж­ные для него дан­ные живут внут­ри это­го объ­ек­та, а не где-то сна­ру­жи в про­грам­ме. Напри­мер, если у меня есть объ­ект «Поль­зо­ва­тель», то у меня в нём будут все дан­ные о поль­зо­ва­те­ле: и имя, и адрес, и всё осталь­ное. И в нём же будут мето­ды «Про­ве­рить адрес» или «Под­пи­сать на рас­сыл­ку».

Абстрак­ция

Мы с вами уже говорили, про абстракцию и о том, что она позволяет нам не задумываться о том, что происходит под капотом того или иного метода.

note

Абстракция это не только про ООП, создавая функцию в своей процедурной/императивной программе вы так же повышаете уровень абстракции.

Абстрак­ция — у объ­ек­та есть интер­фейс: у объ­ек­та есть мето­ды и свой­ства, к кото­рым мы можем обра­тить­ся извне это­го объ­ек­та. Так же, как мы можем нажать кноп­ку на блен­де­ре. У блен­де­ра есть мно­го все­го внут­ри, что застав­ля­ет его рабо­тать, но на глав­ной пане­ли есть толь­ко кноп­ка. Вот эта кноп­ка и есть абстракт­ный интер­фейс.

В про­грам­ме мы можем ска­зать: "Уда­лить поль­зо­ва­те­ля". На язы­ке ООП это будет user.delete() — то есть мы обра­ща­ем­ся к объ­ек­ту user и вызы­ва­ем метод delete. Кайф в том, что нам не так важ­но, как имен­но будет про­ис­хо­дить уда­ле­ние: ООП поз­во­ля­ет нам не думать об этом в момент обра­ще­ния.

Напри­мер, над мага­зи­ном рабо­та­ют два про­грам­ми­ста: один пишет модуль зака­за, а вто­рой — модуль достав­ки. У пер­во­го в объ­ек­те order есть метод revoke. И вот вто­ро­му нуж­но из-за достав­ки отме­нить заказ. И он спо­кой­но пишет: order.revoke(). Ему неваж­но, как дру­гой про­грам­мист будет реа­ли­зо­вы­вать отме­ну: какие он отпра­вит пись­ма, что запи­шет в базу дан­ных, какие выве­дет пре­ду­пре­жде­ния.

Наследование

Насле­до­ва­ние — спо­соб­ность к копи­ро­ва­нию. ООП поз­во­ля­ет созда­вать мно­го объ­ек­тов по обра­зу и подо­бию дру­го­го объ­ек­та. Это поз­во­ля­ет не копи­па­стить код по две­сти раз, а один раз нор­маль­но напи­сать и потом мно­го раз исполь­зо­вать.

Напри­мер, у вас может быть некий иде­аль­ный объ­ект User: в нём вы про­пи­сы­ва­е­те всё, что может про­ис­хо­дить с поль­зо­ва­те­лем. У вас могут быть свой­ства: name, age, address, card_number. И могут быть мето­ды enable_sale, repeat_last_order, get_all_orders, call.

На осно­ве это­го иде­аль­но­го поль­зо­ва­те­ля вы може­те создать реаль­но­го «Поку­па­те­ля Ива­на». У него при созда­нии будут все свой­ства и мето­ды, кото­рые вы зада­ли у иде­аль­но­го поку­па­те­ля, плюс могут быть какие-то свои, если захо­ти­те.

Иде­аль­ные объ­ек­ты про­грам­ми­сты назы­ва­ют клас­са­ми.

Полиморфизм

Поли­мор­физм — еди­ный язык обще­ния. В ООП важ­но, что­бы все объ­ек­ты обща­лись друг с дру­гом на понят­ном им язы­ке. И если у раз­ных объ­ек­тов есть метод delete, то он дол­жен делать имен­но это и писать­ся вез­де оди­на­ко­во. Нель­зя, что­бы у одно­го объ­ек­та это было delete, а у дру­го­го erase.

При этом внут­ри объ­ек­та мето­ды могут быть реа­ли­зо­ва­ны по-разному. Напри­мер, уда­лить товар — это выдать пре­ду­пре­жде­ние, а потом поме­тить товар в базе дан­ных как уда­лён­ный. А уда­лить поль­зо­ва­те­ля — это отме­нить его покуп­ки, отпи­сать от рас­сыл­ки и заар­хи­ви­ро­вать исто­рию его поку­пок. Собы­тия раз­ные, но для про­грам­ми­ста это неваж­но. У него про­сто есть метод delete, и он ему дове­ря­ет.

note

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

Виды полиморфизма

  • Ad hoc - Способ полиморфизма через перегрузку операторов или перегрузку функций
  • Параметризованный полиморфизм - Через написание функций/классов способных работать с различными типами
  • Полиморфизм через подтипы
danger

TODO: Дописать

Наследование в Javascript

В Javascript используется так называемое Прототипное наследование. Т.е одни объекты могут быть прототипами(образцами) для других, что позволяет нам:

  • Не дублировать методы у схожих объектов
  • Реализовывать полиморфизм через подклассы
  • Лучше выражать доменную область

Цепочка прототипов

Функция-конструктор

Это функция которая как мы понимаем по названию что-то конструирует.. конструировать она будет однотипные объекты, которые будут являться экземплярами одного класса. Такие функции мы можем называть и классами.