ООП і TypeScript
У розробці є два підходи до розробки коду:
Функціональне Програмування
Об'єктно-Орієнтоване Програмування
Функціональний підхід у програмуванні орієнтований на використання функцій як базових елементів програми та на використання концепцій функціонального програмування, таких як вищий порядок функцій, замикання (closures), і імутабельність (immutability). Більшість раніше розглянутого коду - було саме функціональне програмування. І такий підхід зручний для невеликих проєктів.
У великих проєктах зручно використовувати Об'єктно-Орієнтований підхід. Тоді виглядає зрозумілішою архітектура застосунку.
Функцію всередині об'єкта називають методом. Змінні класу або об'єкта називають властивостями.
Класи та об'єкти
Клас - це шаблон на базі якого буде створено об'єкт. Клас визначає атрибути (властивості) та методи, які буде мати об'єкт, створений на його основі.
Клас можна уявити як конструктор або заготовку для створення об'єктів. Він містить властивості (змінні) та методи (функції), які можуть бути використані об'єктами цього класу. Об'єкти, створені на основі класу, називаються екземплярами класу.
Розглянемо приклад створення класу Car.
У цьому прикладі Car - це клас. У класі визначено три властивості (brand, model, year) і метод displayInfo, який повертає рядок з інформацією про автомобіль.
Тепер на основі класу можна створити скільки завгодно об'єктів на основі класу Car (в цьому випадку myCar1 і myCar2), і метод displayInfo викликається для виведення інформації про автомобіль.
Подивімось що ж побачимо в консолі, якщо виведемо myCar1
Цей обʼєкт містить 3 властивості, а метод displayInfo міститься уже в його прототипі. Але чудово відпрацьовує для нашого екземпляра автомобіля.
Наш створений автомобіль має чітку структуру визначену класом і має чітко визначений набір метолів для роботи з ним.
Концепції ООП
Інкапсуляція
Інкапсуляція - це одна з основних концепцій об'єктно-орієнтованого програмування, яка дозволяє обмежити доступ до певних даних або методів об'єкта та приховати деталі реалізації.
З назви видно, що клас - як капсула. Назовні виходить тільки те, що повинні бачити, а реалізація прихована.
Це означає, що властивості та методи можуть бути доступні лише в межах самого об'єкта або в межах класу, в якому вони визначені, а не ззовні. Це допомагає уникнути неправильного використання та непередбачених змін даних, забезпечуючи безпеку та правильність програми.
У JavaScript відсутні стандартні ключові слова для визначення модифікаторів доступу (таких як private, protected або public), як у більш строго типізованих мовах, таких як TypeScript або Java.
Інкапсуляцію у чистому JavaScript можна досягти за допомогою замикань (closures).
Як бачимо, властивість speed - захищена і ми до неї можемо звернутися лише за допомогою публічних методів.
Також інкапсуляцію у чистому JavaScript можна реалізувати, якщо винести логіку за межі об'єкта.
Тут отримати доступ до приватного методу protectedMethod можна лише за допомогою публічного методу myPublicMethod. Напряму з обʼєкта метод protectedMethod ми отримати не можемо.
У TypeScript це реалізують за допомогою модифікаторів для методів та властивостей. Наприклад, можна вказати чи метод або властивість публічні, чи приватні. (Як побачили вище в чистому JavaScript модифікаторів немає). Реалізуймо схожий функціонал на TypeScript.
Звернення ззовні класу до приватних та захищених властивостей та методів одразу видасть помилку. Так робити не можна, тому видалимо ці частини коду і подивимось, що покаже в консолі браузера.
У цьому прикладі властивість speed є приватною, тому до неї можна звертатися лише в межах класу Car. Властивість brand є публічною, тому до неї можна звертатися ззовні класу. Властивість model є захищеною, тому до неї можна звертатися в межах класу Car та його підкласів. Також публічний метод getSpeed() можна використовувати ззовні класу, але приватний метод setSpeed() та захищений метод displayInfo() можна використовувати лише всередині класу Car.
Наслідування
Наслідування - це концепція об'єктно-орієнтованого програмування, яка дозволяє створювати новий клас на основі вже існуючого класу, спадковуючи його атрибути (властивості) та методи. Клас, від якого спадкується інший клас, називається батьківським класом або суперкласом, а клас, який спадковує атрибути та методи, - дочірнім класом або підкласом. Наслідування дозволяє використовувати функціональність вже існуючого класу та розширювати її в новому класі.
Синтаксис в es6 та ts - однаковий.
Наслідування дозволяє створювати ієрархії класів, де дочірні класи можуть успадковувати та розширювати функціональність батьківських класів.
Поліморфізм
Поліморфізм - це концепція об'єктно-орієнтованого програмування, яка дозволяє використовувати ті самі інтерфейси чи методи для обробки об'єктів різних класів. Це дозволяє створювати загальні інтерфейси для обробки різних типів об'єктів та забезпечує гнучкість та повторне використання коду.
Одним з прикладів поліморфізму є використання спільного методу з різних класів.
Абстракція
Абстракція - це концепція об'єктно-орієнтованого програмування, яка дозволяє приховувати деталі реалізації та надавати користувачеві лише необхідний функціонал. Це робить програмування більш зрозумілим і зручним для користувачів класу або модуля. Абстракція дозволяє визначити загальний інтерфейс, який незалежний від конкретної реалізації.
Приклад абстракції - це не прописувати весь функціонал в один метод, а розбити його на дрібніші методи і створити фінальний метод, так би мовити, абстракцію над всіма іншими.
Наприклад, Ми приймаємо дві сторони прямокутника і маємо показати повідомлення про площу фігури і периметр. Нема потреби робити це в одному методі. Можна створити метод визначення площі, метод визначення периметра і фінальний метод виведення результату.
Принципи ООП (S.O.L.I.D)
S.O.L.I.D - це абревіатура, яка представляє п'ять основних принципів об'єктно-орієнтованого програмування (ООП) і допомагає створювати чистий, ефективний та легко зрозумілий код.
Принцип одиничної відповідальності (Single Responsibility Principle - SRP): Клас повинен мати лише одну задачу. Це означає, що клас повинен виконувати лише одну функцію або завдання. Якщо клас має більше одного завдання, його слід розділити на декілька класів. Наприклад, якщо клас працює з базою даних, то він працює тільки з базою даних тощо.
Принцип відкритості/закритості (Open/Closed Principle - OCP): Програмні сутності (класи, модулі, функції тощо) повинні бути відкритими для розширення, але закритими для змін. Це означає, що ви можете розширювати їх функціонал, не змінюючи існуючий код. Наприклад, можна написати ще додатковий метод. Але не змінювати вже існуючий, бо від нього можуть залежати інші методи і при зміні може посипатися весь код.
Принцип підстановки Барбари Лісков (Liskov Substitution Principle - LSP): Об'єкти базового класу повинні бути замінені об'єктами його похідних класів без зміни правильності програми. Це означає, що ви повинні мати можливість використовувати підкласи там, де очікується базовий клас, і програма все одно має поводитися коректно.
Принцип розділення інтерфейсу та реалізації (Interface Segregation Principle - ISP): Клієнти не повинні залежати від інтерфейсів, які вони не використовують. Це означає, що інтерфейси повинні бути невеликими та специфічними для конкретних клієнтів, а не великими та загальними.
Принцип інверсії залежності (Dependency Inversion Principle - DIP): Модулі високого рівня не повинні залежати від модулів низького рівня. Обидва повинні залежати від абстракцій. Це означає, що класи високого рівня не повинні залежати від класів низького рівня, а обидва повинні залежати від абстракцій (інтерфейсів або абстрактних класів).
Ці принципи є основами доброї практики об'єктно-орієнтованого програмування і допомагають робити код більш зрозумілим, гнучким та легко змінюваним. Їх використання сприяє створенню високоякісних, масштабованих та легко супроводжуваних програм.
Last updated