Об'єктно-орієнтоване програмування
Парадигми програмування |
---|
|
Об'є́ктно-орієнто́ване програмува́ння[1] (ООП, іноді об'єктно-зорієнто́ване програмува́ння[2][1][3]; англ. Object-oriented programming, OOP) — одна з парадигм програмування, яка розглядає програму як множину «об'єктів», що взаємодіють між собою.[4] Основу ООП складають такі концепції як: інкапсуляція, успадкування, поліморфізм та абстракція. Однією з переваг ООП є краща модульність програмного забезпечення (тисячу функцій процедурної мови, в ООП можна замінити кількома десятками класів із своїми методами). Попри те, що ця парадигма з'явилась в 1960-х роках, вона не мала широкого застосування до 1990-х, коли розвиток комп'ютерів та комп'ютерних мереж дав змогу писати надзвичайно об'ємне і складне програмне забезпечення, що змусило переглянути підходи до написання програм. На теперешній час багато мов програмування або підтримують ООП (PHP, Lua) або ж є цілком об'єкто-орієнтованими (зокрема, Java, C#, C++, Python, Ruby і Objective-C, ActionScript 3, Swift, Vala).
Об'єктно-орієнтоване програмування сягає своїм корінням до створення мови програмування Симула в 1960-х роках, одночасно з посиленням дискусій про кризу програмного забезпечення[en]. Через ускладнення апаратного та програмного забезпечення було дуже важко зберегти якість програм. Об'єкто-орієнтоване програмування частково розв'язує цю проблему шляхом наголошення на модульності програми[5].
На відміну від традиційних поглядів, коли програму розглядали як набір підпрограм, або як перелік інструкцій комп'ютеру, ООП-програми можна вважати сукупністю об'єктів. Відповідно до парадигми об'єктно-орієнтованого програмування, кожен об'єкт здатний отримувати повідомлення, обробляти дані, та надсилати повідомлення іншим об'єктам. Кожен об'єкт — своєрідний незалежний автомат з окремим призначенням та відповідальністю[6].
На думку Алана Кея, розробника мови Smalltalk, якого вважають одним з «батьків-засновників» ООП, об'єкто-орієнтований підхід полягає в наступному наборі основних принципів:
- Все є об'єктами.
- Всі дії та розрахунки виконуються шляхом взаємодії (обміну даними) між об'єктами, під час якої один об'єкт потребує, щоб інший об'єкт виконав деяку дію. Об'єкти взаємодіють, надсилаючи й отримуючи повідомлення. Повідомлення — це запит на виконання дії, доповнений набором аргументів, які можуть знадобитися під час виконання дії.
- Кожен об'єкт має незалежну пам'ять, яка складається з інших об'єктів.
- Кожен об'єкт є представником (екземпляром, примірником) класу, який виражає загальні властивості об'єктів.
- У класі задається поведінка (функціональність) об'єкта. Таким чином усі об'єкти, які є екземплярами одного класу, можуть виконувати одні й ті ж самі дії.
- Класи організовані у єдину деревоподібну структуру з загальним корінням, яка називається ієрархією успадкування. Пам'ять та поведінка, зв'язані з екземплярами деякого класу, автоматично доступні будь-якому класу, розташованому нижче в ієрархічному дереві.
Таким чином, програма є набором об'єктів, що мають стан та поведінку. Об'єкти взаємодіють використовуючи повідомлення. Будується ієрархія об'єктів: програма в цілому — це об'єкт, для виконання своїх функцій вона звертається до об'єктів що містяться у ньому, які своєю чергою виконують запит шляхом звернення до інших об'єктів програми. Звісно, щоб уникнути нескінченної рекурсії у зверненнях, на якомусь етапі об'єкт трансформує запит у повідомлення до стандартних системних об'єктів, що даються мовою та середовищем програмування. Стійкість та керованість системи забезпечуються шляхом чіткого розподілу відповідальності об'єктів (за кожну дію відповідає певний об'єкт), однозначного означення інтерфейсів міжоб'єктної взаємодії та повної ізольованості внутрішньої структури об'єкта від зовнішнього середовища (інкапсуляції).
ООП виникло в результаті розвитку ідеології процедурного програмування, де дані й підпрограми (процедури, функції) їх обробки формально не пов'язані. Для подальшого розвитку об'єктоорієнтованого програмування велике значення мають поняття події (так зване подієво-орієнтоване програмування) і компоненти (компонентне програмування, КОП).
Формування КОП від ООП відбулося, так само як формування модульного від процедурного програмування: процедури сформувалися в модулі — незалежні частини коду до рівня збірки програми, так об'єкти сформувалися в компоненти — незалежні частини коду до рівня виконання програми. Взаємодія об'єктів відбувається за допомогою повідомлень. Результатом подальшого розвитку ООП, мабуть, буде агентно-орієнтоване програмування, де агенти — незалежні частини коду на рівні виконання. Взаємодія агентів відбувається за допомогою зміни середовища, в якій вони знаходяться.
Мовні конструкції, конструктивно не пов'язані безпосередньо з об'єктами, але необхідні їм для їх безпечної (виняткові ситуації, перевірки) та ефективної роботи, інкапсулюються від них в аспекти (в аспектно — орієнтованому програмуванні). Суб'єктно-орієнтоване програмування розширює поняття об'єктів шляхом забезпечення більш уніфікованої і незалежної взаємодії об'єктів. Може бути перехідною стадією між ООП та агентним програмуванням в частині самостійної їх взаємодії.
Першою мовою програмування, в якій були запропоновані принципи об'єктної орієнтованості, була Симула. На момент своєї появи (в 1967 році), ця мова програмування запропонувала революційні ідеї: об'єкти, класи, віртуальні методи тощо, однак це все не було сприйнято сучасниками як щось грандіозне. Проте, більшість концепцій були розвинені Аланом Кеєм та Деном Інгаллсом[en] у мові Smalltalk. Саме вона стала першою широко поширеною об'єкто-орієнтованою мовою програмування.
Наразі кількість прикладних мов програмування (список мов), що реалізують об'єкто-орієнтовану парадигму, є найбільшим стосовно інших парадигм. В області системного програмування досі застосовується парадигма процедурного програмування, і загальноприйнятою мовою програмування є мова C. Хоча при взаємодії системного і прикладного рівнів операційних систем стали помітно впливати мови об'єкто-орієнтованого програмування. Наприклад, однією з найпоширеніших бібліотек мультиплатформового програмування є об'єкто-орієнтована бібліотека Qt, написана мовою C++.
В результаті дослідження Дебори Дж. Армстронг[7] комп'ютерної літератури, що була видана протягом останніх 40 років, вдалось відокремити фундаментальні поняття (принципи), використані у переважній більшості визначень об'єкто-орієнтованого програмування. До них належить:
Клас визначає абстрактні характеристики деякої сутності, включно з характеристиками самої сутності (її атрибутами або властивостями) та діями, які вона здатна виконувати (її поведінкою, методами або можливостями). Наприклад, клас Собака
може характеризуватись рисами, притаманними всім собакам, зокрема: порода, колір хутра, здатність гавкати. Класи вносять модульність та структурованість в об'єкто-орієнтовану програму. Зазвичай клас має бути зрозумілим для не-програмістів, що знаються на предметній області, що, своєю чергою, значить, що клас повинен мати значення в контексті. Також, код реалізації класу має бути досить самодостатнім. Властивості та методи класу, разом називаються його членами.
Окремий екземпляр класу (створюється після запуску програми та ініціалізації полів класу). Клас Собака
відповідає всім собакам шляхом опису їхніх спільних рис; об'єкт Сірко
є одним окремим собакою, окремим варіантом значень характеристик. Собака
має хутро; Сірко
має коричнево-біле хутро. Об'єкт Сірко
є екземпляром (примірником) класу Собака.
Сукупність значень атрибутів окремого об'єкта називається станом. На основі класу Собака
можна, також, створити інший об'єкт Дружок
, який відрізнятиметься від об'єкта Сірко
своїм станом (наприклад кольором хутра). Обидва об'єкти (Сірко і Дружок) є екземплярами класу Собака
.
Можливості об'єкта. Оскільки Сірко
— Собака
, він може гавкати. Тому гавкати()
є одним із методів об'єкта Сірко
. Він може мати й інші методи, зокрема: місце()
, або їсти()
. В межах програми, використання методу має впливати лише на один об'єкт; всі Собаки
можуть гавкати, але треба, щоб гавкав лише один окремий собака.
«Передача даних від одного процесу іншому, або надсилання викликів методів.»
Приховування деталей про роботу класів від об'єктів, що їх використовують або надсилають їм повідомлення. Так, наприклад, клас Собака
має метод гавкати()
. Реалізація цього методу описує як саме повинно відбуватись гавкання (приміром, спочатку вдихнути()
, а потім видихнути()
на обраній частоті та гучності). Петро, хазяїн пса Сірка
, не повинен знати як він гавкає. Інкапсуляція досягається шляхом вказування, які класи можуть звертатися до членів об'єкта. Як наслідок, кожен об'єкт надає кожному іншому класу певний інтерфейс — члени, доступні іншим класам. Інкапсуляція потрібна для того, аби запобігти використанню користувачами інтерфейсу тих частин реалізації, які, швидше за все, будуть змінюватись. Це дасть змогу полегшити внесення змін без потреби змінювати й користувачів інтерфейсу. Наприклад, інтерфейс може гарантувати, що щенята можуть додаватись лише до об'єктів класу Собака
кодом самого класу. Часто, члени класу позначаються як публічні (англ. public), захищені (англ. protected) та приватні (англ. private), визначаючи, чи доступні вони всім класам, підкласам, або лише до класу в якому їх визначено. Деякі мови програмування йдуть ще далі: Java використовує ключове слово private для обмеження доступу, що буде дозволений лише з методів того самого класу, protected — лише з методів того самого класу і його нащадків та з класів із того ж самого пакету, C# та VB.NET відкривають деякі члени лише для класів із тієї ж збірки шляхом використання ключового слова internal (C#) або Friend (VB.NET), а Eiffel дозволяє вказувати які класи мають доступ до будь-яких членів.
Клас може мати «підкласи», спеціалізовані, розширені версії надкласу. Можуть навіть утворюватись цілі дерева успадкування. Наприклад, клас Собака
може мати підкласи Коллі
, Пекінес
, Вівчарка
тощо. Так, Сірко
може бути екземпляром класу Вівчарка
. Підкласи успадковують атрибути та поведінку своїх батьківських класів, і можуть вводити свої власні. Успадкування може бути одиничне (один безпосередній батьківський клас) та множинне (кілька батьківських класів). Це залежить від вибору програміста, який реалізовує клас та мови програмування. Так, наприклад, в Java дозволене лише одинарне успадкування, а в С++ і те й інше.
Спрощення складної дійсності шляхом моделювання класів, що відповідають проблемі, та використання найприйнятнішого рівня деталізації окремих аспектів проблеми. Наприклад Собака
Сірко
більшу частину часу може розглядатись як Собака
, а коли потрібно отримати доступ до інформації специфічної для собак породи коллі — як Коллі
і як Тварина
(можливо, батьківський клас Собака
) під час підрахунку тварин Петра.
Існує декілька видів поліморфізму в програмуванні. Один реалізовується шляхом реалізації ряду підпрограм (функцій, процедур, методів тощо) з однаковими іменами, але з різними параметрами. Залежно від того, що передається, і вибирається відповідна підпрограма. Щодо власне ООП, то під поліморфізмом розуміється можливість використання об'єктів(екземплярів) підкласів взамін батьківського класу. При цьому в кожному класі реалізуються одні і ті ж підпрограми з одними і тими ж параметрами. Так можна реалізувати клас Тварина
, з підкласами Свиня
та Собака
. Оскільки підкласи матимуть один інтерфейс взаємодії, тобто в кожному реалізований метод голос()
, то можна підставляти в один і той же код, замість батьківського класу, об'єкт одного з підкласів і отримати різний звук або Гав
, або Рох-рох
. На практиці, підставновка реалізується шляхом присвоєнню змінній з типом батьківського класу (Тварина
) посилання на об'єкт підкласу (на Свиня
або Собака
).
Не всі з перелічених вище концепцій присутні в усіх об'єкто-орієнтованих мовах програмування. Зокрема, в прототипно-орієнтованому програмуванні не використовуються класи. Як наслідок, зовсім інша, але аналогічна термінологія використовується для визначення об'єкта та екземпляра в цих мовах.
У мовах, які підтримують відкриту рекурсію, об'єктні методи можуть викликати інші методи того самого об'єкта (включаючи себе), як правило, використовуючи спеціальну змінну або ключове слово під назвою this
або self
. Ця змінна має пізнє прив'язування; це дозволяє методу, визначеному в одному класі, викликати інший метод, який визначено пізніше, в якомусь його підкласі.
Перша ООП мова — Simula (1967). Smalltalk (1972 — 1980) ще один приклад ранніх ООП мов, на якій відбувалось апробація принципів ООП. Неповний список ООП мов:
- ActionScript (3.0)
- Ada
- C#
- C++
- Cyclone
- D
- Dylan[8]
- Eiffel
- F#
- Io
- Java[9]
- JavaScript[10][11][12]
- JScript. NET
- Object Pascal
- Objective-C[13]
- Perl
- PHP[14]
- PowerBuilder
- Python[15]
- Ruby
- Scala
- Swift[16]
- Vala[17]
- VB.NET
- Visual DataFlex[ru]
- Xbase++[en]
- X++
- Результати дослідження Томаса Потока та інших не показали істотної різниці у продуктивності між ООП та процедурним підходами.[18]
- Крістофер Дейт заявляє, що критичне порівняння ООП з іншими технологіями, зокрема, реляційною практикою є дуже складним через відсутність узгодженості та чіткого визначення ООП[19]
- Едсгер Дейкстра "… чого суспільство переважно вимагає, так це панацеї. Звісно, панацея має різноманітні назви — інакше ви не продали б нічого подібного до «Structured Analysis and Design», «Software Engineering», «Maturity Models», «Management Information Systems», «Integrated Project Support Environments» «Object Orientation» та «Business Process Re-engineering» (останні відоміші, як IPSE, OO та BPR відповідно)."[20]
- Мова програмування
- Парадигма програмування
- Компонентно-орієнтоване програмування
- Проектування за контрактом
- Композиція (програмування)
- UML
- Закон Деметри
- Макет об'єкта
- Мультипарадигмальна мова програмування
- ↑ а б object-oriented // Англійсько-українсько-англійський словник наукової мови (фізика та споріднені науки). Частина І англійсько-українська / уклад. О. Кочерга, Є. Мейнарович. — 2010.
- ↑ object-oriented // Англійсько-український словник з математики та інформатики / уклад. Є. Мейнарович, М. Кратко. — 2010.
- ↑ object-oriented // Українсько-англійський словник з радіоелектроніки / Богдан Рицар, Леонід Сніцарук, Роман Мисак. — 2015.
- ↑ Гради Буч, Роберт А. Максимчук, Майкл У. Энгл, Бобби Дж. Янг, Джим Коналлен, Келли А. Хьюстон. Объектно-ориентированный анализ и проектирование с примерами приложений. М.: Вильямс, 2008.- 720с.
- ↑ Meyer, chapter 3
- ↑ Booch, chapter 2
- ↑ Armstrong, 2006.
- ↑ Команда разработчиков BLFS, «За пределами проекта „Linux® с нуля“». Версия 7.4, Том 1, стр.622
- ↑ Java. Объектно-ориентированное программирование с интерфейсами. Архів оригіналу за 16 серпня 2019. Процитовано 31 січня 2020.
- ↑ Введение в объектно-ориентированный JavaScript
- ↑ Понимание ООП в JavaScript
- ↑ ООП в функциональном стиле JavaScript. Архів оригіналу за 14 липня 2019. Процитовано 31 січня 2020.
- ↑ Разработка под Apple. Objective-C
- ↑ PHP: Основы ООП
- ↑ Введение в объектно-ориентированное программирование (ООП) на Python. Архів оригіналу за 7 серпня 2015. Процитовано 31 січня 2020.
- ↑ Apple Inc., «The Swift Programming Language», 2014
- ↑ Объектно-ориентированное программирование на языке Vala
- ↑ Potok, Thomas; Mladen Vouk; Andy Rindos (1999). Productivity Analysis of Object-Oriented Software Developed in a Commercial Environment (PDF). Software – Practice and Experience. 29 (10): 833—847. doi:10.1002/(SICI)1097-024X(199908)29:10<833::AID-SPE258>3.0.CO;2-P. ISSN 0038-0644. Процитовано 21 квітня 2010. (англ.)
- ↑ C. J. Date, Introduction to Database Systems, 6th-ed., Page 650 (англ.)
- ↑ EWD 1175 The strengths of the academic enterprise (англ.)
- Armstrong, Deborah J. (February 2006). The Quarks of Object-Oriented Development. Communications of the ACM. 49 (2): 123—128. ISSN 0001-0782. Процитовано 8 серпня 2006.
- Meyer, Bertrand (1997). Object-Oriented Software Construction[en]. Prentice Hall. ISBN 0-13-629155-4.