DRAFT [2022-2023][ua] at 2023-05-03 17:18:24 +0300
Logo-do [errata] Profile

Frontend-розробка SPA Web-додатків

Об'єктно-орієнтоване програмування

Конспект лекції


12 ОБ'ЄКТНО-ОРІЄНТОВАНЕ ПРОГРАМУВАННЯ

У цьому розділі ми дізнаємося, як створювати і використовувати об'єкти в рамках об'єктно-орієнтованого програмування. Об'єктно-орієнтоване програмування (ООП) – це спосіб проектування і написання коду, коли всі важливі частини програми є об'єктами. Наприклад, якщо ви пишете відеогру «гонки», ви можете скористатися технологією ООП і запрограмувати об'єкт «машина», а потім створити безліч таких об'єктів, що володіють однаковим набором властивостей і однаковою функціональністю.

Простий об'єкт

Як ви вже знаєте з четвертого розділу, об'єкти складаються з властивостей, які представляють собою пари «ключ-значення». Наприклад, в наступному коді об'єкт dog описує собаку, і у нього є властивості – name (ім'я), legs (кількість лап) і isAwesome (позначає, чи хороша ця собака):

var dog = {
name: "Рекс",
legs: 4,
isAwesome: true
};

До властивостей створеного об'єкта можна звертатися через точкову нотацію. Наприклад, так ми можемо отримати властивість name нашого об'єкта dog:

Крім того, за допомогою точкової нотації можна додавати об'єкту нові властивості:

При цьому у об'єкта з'явиться ще одна пара «ключ-значення» (age: 6).

Додавання до об'єктів нових методів

В останньому прикладі ми створили кілька властивостей, які зберігають значення різних типів: рядок ( "Рекс"), числа (4 і 6) і булеве значення (true). Крім рядків, чисел і булевих значень у властивостях об'єктів можна зберігати функції - тоді ці властивості називають методами. По суті, ми вже користувалися деякими вбудованими в JavaScript методами: наприклад, це метод join для масивів і метод toUpperCase для рядків.

А тепер давайте подивимося, як створювати власні методи.

Один із способів - скористатися точковою нотацією. Наприклад, навчимо нашу собаку гавкати, додавши до об'єкта dog метод під назвою bark:

Спочатку ми додали до об'єкта dog властивість bark і задали в якості її значення функцію. В тілі цієї функції, ми використовували console.log, щоб надрукувати: «Гав-гав! Мене звуть Рекс! » Зверніть увагу на запис this.name – таким чином ми отримуємо значення, збережене в властивості name цього об'єкта.

Давайте розберемося докладніше, як працює ключове слово this.

Ключове слово this

Ключове слово this можна використовувати в тілі методу, щоб звернутися до об'єкта, для якого цей метод викликається. Наприклад, при виклику методу bark для об'єкта dog, this позначає об'єкт dog, а значить this.name – це властивість dog.name. Ключове слово this робить методи більш гнучкими, дозволяючи додавати один і той же метод до багатьох об'єктів так, щоб він мав доступ до властивостей того об'єкту, для якого в даний момент викликається.

Використовуємо один метод з різними об'єктами

Давайте створимо нову функцію speak, щоб потім використовувати її як метод з різними об'єктами, які позначають різних тварин.

У разі виклику для якого-небудь об'єкта метод speak буде звертатися до імені об'єкта (this.name) і звуку, який видає тварина (this.sound), щоб вивести в консоль повідомлення.

var speak = function () {
console.log(this.sound + "! Мене звуть " + this.name + "!");
};

Тепер створимо ще один об'єкт, щоб додати до нього функцію speak як метод:

var cat = {
sound: "Мяу",
name: "Рукавичка",
speak: speak
};

Тут ми створили новий об'єкт cat з властивостями sound, name і speak. У рядку ми присвоїли властивості speak значення – створену раніше функцію speak. Тепер cat.speak є методом, який можна викликати командою cat.speak(). Оскільки в коді методу використовується ключове слово this, в разі виклику для об'єкта cat він отримає доступ до властивостей саме цього об'єкта.

Давайте перевіримо:

cat.speak();

Коли ми викликаємо метод cat.speak, він запитує значення двох властивостей об'єкта cat: this.sound (це "Мяу") і this.name (це "Рукавичка").

Ту ж саму функцію speak можна використовувати як метод і для інших об'єктів:

var pig = {
sound: "Хрю",
name: "Чарлі",
speak: speak
};
var horse = {
sound: "І-го-го",
name: "Мері",
speak: speak
};

pig.speak();
horse.speak();

Щоб використовувати один і той же код методу з різними об'єктами, досить додати його у вигляді властивості кожному з цих об'єктів - це ми і зробили зараз з функцією speak. Однак якщо в програмі багато об'єктів і методів, додавання методів вручну буде завданням вельми стомлюючим, а код при цьому стане заплутаним і неакуратним. Тільки уявіть, що вам потрібен цілий зоопарк об'єктів для сотні різних тварин і ви хочете, щоб у них всіх було з десяток загальних методів і властивостей. Конструктори об'єктів дозволяють задавати загальні методи і властивості куди більш зручним способом.

Створення об'єктів за допомогою конструкторів

В JavaScript конструктор – це функція, яка створює об'єкти, даючи їм набір заздалегідь визначених властивостей і методів. Задавши конструктор, ви зможете створювати з його допомогою будь-яку кількість однакових об'єктів. Щоб випробувати цей підхід в справі, ми напишемо основу гри «гонки», де використаємо конструктор для створення парку машин з однаковими базовими властивостями, а також методами для переміщення в різні боки і зміни швидкості.

Структура конструктора

При кожному виклику конструктор створює об'єкт, додаючи йому потрібні властивості. Якщо для виклику звичайної функції ми вказували її ім'я і слідом круглі дужки, то для виклику конструктора використовується ключове слово new (яке повідомляє JavaScript, що ви збираєтеся використовувати функцію як конструктор), а слідом - ім'я конструктора і дужки.

Створюємо конструктор Car

Давайте створимо конструктор Car, який буде додавати до кожного створеного об'єкту властивості x і y. Ми будемо використовувати ці властивості як координати, що задають позицію машини на екрані при відображенні.

Створюємо HTML-документ

Перш ніж писати код конструктора, нам потрібно створити новий HTML документ. Створіть новий файл під ім'ям cars.html і введіть в нього наступний HTML-код:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Гонки</title>
</head>
<body>
<script src="https://code.jquery.com/jquery-2.1.0.js"></script>
<script>
// Тут буде JavaScript-код
</script>
</body>
</html>

Функція-конструктор Car

Тепер введіть наступний код між тегів <script> в файлі cars.html (Замість коментаря "// Тут буде JavaScript-код"), щоб створити конструктор Car, який додає кожному об'єкту-машині пару координат.

<script>
var Car = function (x, y) {
this.x = x;
this.y = y;
};
</script>

Наш новий конструктор приймає два аргументи, x і y, і додає новому об'єкту властивості this.x і this.y, зберігаючи в них передані значення x і y. Таким чином, кожен раз при виклику конструктора Car буде створений новий об'єкт з властивостями x і y, значення яких відповідають переданим аргументам.

Виклик конструктора Car

Як я вже говорив, ключове слово new вказує JavaScript, що ми викликаємо конструктор для створення нового об'єкта. Наприклад, щоб створити об'єкт-машину з ім'ям tesla, відкрийте файл cars.html в браузері і введіть в JavaScript-консолі Chrome такий код:

Код Car (10, 20) вказує JavaScript, що потрібно створити об'єкт, використовуючи функцію Car як конструктор і передавши їй аргументи 10 і 20 для властивостей x і y, і потім повернути цей об'єкт. Отриманий новий об'єкт ми зберігаємо в змінній tesla.

Далі, коли ми ввели tesla, консоль Chrome надрукувала ім'я конструктора і властивості x і y: Car {x: 10, y: 20}

Рисуємо машини

Для відображення об'єктів, створених конструктором Car, створимо функцію під назвою drawCar - вона буде розміщувати зображення машини в позицію (x, y), що відповідає властивостям x і y кожного нашого об'єкта. Розібравшись, як ця функція працює, ми перепишемо її в об'єктно-орієнтованому вигляді. Введіть цей код між тегів <script> в файлі cars.html:

<script>
var Car = function (x, y) {
this.x = x;
this.y = y;
};
var drawCar = function (car) {
var carHtml = '<img src="https://a.d-cd.net/2bd7a44s-960.jpg">';
var carElement = $(carHtml);
carElement.css({
position: "absolute",
left: car.x,
top: car.y
});
$("body").append(carElement);
};
</script>

Спочатку ми створили рядок з HTML-кодом, що містить посилання на зображення машини. Далі ми передаємо carHTML в функцію $, яка перетворює HTML в jQuery елемент. Це означає, що в змінній carElement тепер зберігається jQuery-елемент з інформацією про тег <img> і ми зможемо змінити властивості цього елемента перед тим, як додати його на сторінку.

Потім ми викликаємо для carElement метод css, щоб задати зображенню машини координати. Цей код встановлює відступ зліва згідно координаті x об'єкта і відступ зверху згідно його координаті y. Іншими словами, у вікні браузера лівий край зображення буде мати відступ від лівої межі вікна на x пікселів, а верхній край зображення буде мати відступ від верхньої межі вікна на y пікселів. І в кінці, ми за допомогою jQuery додаємо carElement до елементу body нашого HTML-документа. Після цього carElement з'явиться на сторінці.

Перевірка функції drawCar

var tesla = new Car(20, 20);
var nissan = new Car(100, 200);
drawCar(tesla);
drawCar(nissan);

Тут ми використовували конструктор Car для створення двох об'єктів - першого з координатами (20, 20) і другого з координатами (100, 200) - і потім відобразили їх у вікні браузера за допомогою drawCar.

Налаштування об'єктів через прототипи

Є інший, більш об'єктно-орієнтований підхід до рисування машин - задати для кожного об'єкта-машини метод відрисовки (назвемо його draw). Тоді замість drawCar (tesla) можна буде написати tesla.draw(). В об'єктно-орієнтованому програмуванні прийнято, щоб об'єкти мали власну функціональність, організовану у вигляді методів. У нашому випадку функція drawCar спочатку призначена для зображення об'єктів-машин, тому варто зробити її частиною кожного об'єкта, а не використовувати як окрему функцію.

Прототипи JavaScript – це механізм, який спрощує використання загальної функціональності (тобто методів) різними об'єктами. У всіх конструкторів є властивість prototype, до якої можна додавати методи; будь-який метод, доданий до властивості prototype, буде доступний всім об'єктам, які створені за допомогою цього конструктора.

Додаємо метод draw до прототипу Car

Давайте додамо метод draw до властивості Car.prototype, щоб він з'явився у всіх об'єктів, створених викликом newCar.

<script>
var Car = function (x, y) {
this.x = x;
this.y = y;
};

Car.prototype.draw = function () {
var carHtml = '<img src="https://a.d-cd.net/2bd7a44s-960.jpg">';
this.carElement = $(carHtml);
this.carElement.css({
position: "absolute",
left: this.x,
top: this.y
});
$("body").append(this.carElement);
};

var tesla = new Car(20, 20);
var nissan = new Car(100, 200);

tesla.draw();
nissan.draw();
</script>

Після створення конструктора ми додали до Car.prototype новий метод draw. Таким чином, draw стане частиною всіх об'єктів, створених конструктором Car. Спочатку ми створюємо рядок з HTML-кодом, зберігаючи його в змінній carHTML. Далі ми створюємо jQuery-елемент для цього HTML, на цей раз зберігаючи його у властивості об'єкта this.carElement. Потім ми, звертаючись до this.x і this.y, задаємо координати верхнього лівого кута зображення. (У конструкторі this відповідає об'єкту, який в даний момент створюється.)

Перевага цього підходу в тому, що тепер код рисунка є частиною об'єкта, а не окремою функцією.

Додаємо метод moveRight

Тепер додамо кілька методів для переміщення машин по екрану, починаючи з методу moveRight, пересуваючого машину на 5 пікселів вправо щодо поточної позиції. Додайте наступний код після визначення Car.prototype.draw:

Car.prototype.moveRight = function () {
this.x += 5;
this.carElement.css({
left: this.x,
top: this.y
});
};

Ми зберегли метод moveRight у властивості Car.prototype, щоб зробити його частиною всіх об'єктів, створених за допомогою конструктора Car. Командою
this.x + = 5 ми збільшуємо координату x машини на 5, щоб перемістити її на 5 пікселів вправо. Потім ми викликаємо метод css для this.carElement, щоб оновити позицію машини в браузері.

Якщо викликати метод moveRight з консолі браузера верхня машина повинна пересунутися вправо на 5 пікселів.

Завдання для самостійної роботи

#1. Додайте можливість керування автомобілем

Доопрацюйте приклад із лекційного заняття, додавши прототипи методів для управління автомобілем вліво, вгору та вниз.

#2. Додайте властивість speed.

Доопрацювати конструктор Car, щоб він додавав до об'єктів властивість speed (швидкість) із значенням 5. Використовуйте цю властивість в методах переміщення замість зазначеного числа.

#3. Гонки

Доопрацювати методи moveLeft, moveRight, moveUp і moveDown, щоб замість переміщення машин завжди рівно на 5 пікселів вони приймали величину зміщення в якості аргументу. Наприклад, в цьому випадку для переміщення машини nissan на 10 пікселів вправо потрібно буде дати команду nissan.moveRight (10).

Використайте setInterval, щоб рухати дві машини (nissan і tesla) вправо, кожні 30 мілісекунд зміщуючи їх на випадкову відстань від 0 до 5 пікселів. Ви побачите, як машини їдуть по екрану, раз у раз змінюючи швидкість. Задайте фінішну границю та виведіть на екран повідомлення із зазначеннням назви автомобіля.

Підказка: назву автомобіля додайте як властивість до конструктора Car.


© 2006—2023 СумДУ