Чи справді нам потрібні мови ОО для управління складністю програмного забезпечення?


209

Це буде дуже нетехнічним, м'яким питанням, і я не впевнений, чи це правильна платформа. Але я початковий студент CS, тож сподіваюся, ви, хлопці, терпите це.

У першому семестрі нас ознайомили з такими поняттями OOP, як інкапсуляція, приховування даних, модульність, успадкування тощо тощо через Java та UML. (Java - моя перша мова програмування)

Як я це розумію, OOP - це спосіб управління складністю програмного забезпечення. Але його принципи не є новими або унікальними, вони в певному сенсі універсальні для всіх інженерних сфер.

Наприклад, автомобіль - це дуже складна структура, складність якої керується ієрархією модульних та інкапсульованих компонентів із чітко визначеними поведінками та інтерфейсами.

Але я не розумію причину введення нової парадигми програмування. Я думаю, що всі принципи управління складністю можуть бути реалізовані процедурними мовами програмування. Наприклад, для модульності ми можемо просто розділити програму на багато невеликих програм, які виконують чітко визначені завдання, код яких міститься в окремих файлах. Ці програми взаємодіють одна з одною через їх чітко визначений вхід та вихід. Файли можуть бути захищені (зашифровані?) Для досягнення інкапсуляції. Для повторного використання коду ми можемо просто викликати ці файли, коли вони знадобляться в нових програмах. Хіба це не охоплює все, що є OOP, або я пропускаю щось дуже очевидне?

Я не прошу доказів, що ООП управляє складністю. На мою думку, це, безумовно, так і є. Але я думаю, що всі принципи, що застосовуються для управління складністю, такі як модульність, інкапсуляція, приховування даних тощо, можуть бути дуже легко реалізовані процедурними мовами. То чому ж насправді OOP, якщо ми можемо керувати складністю без цього?


41
Вам не вистачає розділення інтерфейсу та реалізації. Можливість замінювати одну реалізацію на іншу під час виконання - дуже важлива особливість. В основному, це досягається динамічним методом диспетчеризації мов ОО з успадкуванням. Процедурні мови також можуть це робити (читайте: недійсні покажчики), але без безпеки типу.
марстато

81
Значною мірою ідея об'єктно-орієнтованих мов та дизайну полягає саме в тому, щоб зробити ці універсальні, інтуїтивні поняття максимально легкими для представлення та відтворення в коді. Якщо у вас була схема або набір вказівок, як досягти всіх цих речей без вродженої об'єктно-орієнтованої мови, то ваші пропозиції щодо того, як це зробити, ефективно використовували б об'єктно-орієнтовану методологію. Фактичні мови OO - це лише спосіб їх формалізації та спрощення.
Резервний час

14
@RobbieDee ти насправді читав моє запитання? Йдеться про спробу зрозуміти ОО на більш фундаментальному рівні, опитуючи погоду, складність програмного забезпечення може бути керована без ОО. Я не намагаюся підірвати ОО, не намагаюся вигадати щось нове, я просто намагаюся зрозуміти це краще, і якщо це питання настільки «очевидне», чому він отримав чудову відповідь від Йорга?
steakexchange

12
Шифрування файлу - це не капсулювання. Можливо, ви затьмарилися, переглядаючи вміст коду від іншого розробника, але ви не обов'язково захищали внутрішню роботу коду від іншого коду. Оригінальний автор міг це зробити до чи після шифрування, якщо він може згадати як.
JeffO

8
Вам не потрібно нічого, крім машинної мови - нехай програміст запам'ятовує коди і сам записує ці та нулі. Але наявність якоїсь "символічної" мови дуже корисна з точки зору зменшення помилок та підвищення продуктивності, і, як зауважив Дейкстра, мова, яка нав'язує певну "структуру" (або, принаймні, полегшує підтримку "структури"). Мови ОО не можуть бути ідеальною технологією, враховуючи сучасний рівень витонченості мови, але вони досить хороші для багатьох програм. Ідея полягає в управлінні складністю, не заважаючи.
Даніель Р Хікс

Відповіді:


177

Дозвольте спробувати дійсно низьку теоретичну відповідь :)

Те, що ви насправді запитуєте, це: навіщо включати підтримку об'єктної орієнтації (ОО) безпосередньо мовою, коли процедурні мови можна використовувати для проектування та написання коду ОО?

А відповідь така: щоб мати стандарт того, як OO виражається у вихідному коді, щоб ви не закінчилися 22 різними реалізаціями для однієї абстракції.

Наприклад, скажімо, що я створюю MagicButtonта MagicSliderякі можна використовувати в системі інтерфейсу користувача. Мені потрібен спосіб згрупувати методи, які можна використовувати з MagicButton, методи, які можна використовувати лише з MagicSlider, і методи, які можуть бути використані обома. Ці об'єкти поділяють деякі методи, оскільки вони обидва об'єкти Magic gui.

Я можу зробити групування, називаючи функції особливим чином MagicSlider_DoSomething ..., включаючи методи у конкретні файли, названі особливим чином MagicSliderMethods.XXX, або я міг знайти якийсь інший спеціальний спосіб зробити те саме. Якщо в мові немає стандартного способу зробити це, я зроблю це не так, як у вас, і від інших. Це значно полегшує обмін кодом.

Так, пізня відправка - віртуальні методи в мовах ОО - можуть бути реалізовані в процедурних мовах, але існує так багато різних способів її реалізації. Залежно від того, хто написав код, ви отримаєте різні реалізації OO всередині однієї програми.

Подумайте про поганий розробник технічного обслуговування. Ця людина повинна керувати різними абстракціями об'єктів та різними способами виклику віртуальних методів залежно від того, хто написав оригінальний код.

Також: Наявність абстракцій у мові дозволяє передовим редакторам коду, таким як Eclipse, робити багато статичного аналізу коду. Наприклад, Eclipse може запропонувати список усіх методів, які можна використовувати на об'єкті, а також автоматичну реалізацію порожніх "методів TODO". Eclispe точно знає, які методи повинен застосовувати ваш клас, на основі класів, які ви розширюєте та які інтерфейси ви реалізуєте. Це було б майже неможливо, якби не було мовного стандарту, щоб зробити ОО.


40
Класичний приклад: Луа. Це не вихідне OO, але його можна зробити, але це означає, що існує близько 5 різних однаково відомих бібліотек OO, які не є цілком сумісними.
Кролтан

55
@steakexchange Ви занадто сильно орієнтуєтесь на абсолюти. Дуже мало має "єдину мету". Всі мови роблять багато різних речей у різній мірі якості. Вибір мови - це вибір набору компромісів, які найкраще підходять для тієї мети, для якої вам це потрібно.
Тім Б

42
@nocomprende Стандартизація абстракцій - це практично буквально те, для чого потрібні мови програмування. Навіть мова монтажу рефератів щодо відмінностей у чомусь на зразок десяти апаратних поколінь протягом півтора десятиліть.
Девід Молес

56
@DavidMoles Стандартизовані абстракції - це буквально те, що є мовами програмування. Не втрачайте ідеальної можливості використовувати "буквально" буквально!
Климент Черлін

12
Це можна стандартизувати. Коли я був в університеті ще в середині 90-х, я провів досить велику роботу в X-Windows (в основному на основі Motif, для тих, хто пам’ятає такі речі). X-Windows дійсно дозволяє реалізувати всі можливості орієнтації об'єкта в звичайному C . Робота з розумовою гімнастикою була досить вагомою, і багато в чому покладалася на людей, які не заглядають усередину коробки (в цей момент Кодекс віджетів Шредінгера, як правило, закінчується мертвим). Мова OO приховує це від кодерів так само, як звичайний компілятор робить для асемблера, і життя простіше.
Грем

211

У першому семестрі нас ознайомили з такими поняттями OOP, як інкапсуляція, приховування даних, модульність, успадкування тощо тощо через Java та UML. (Java - моя перша мова програмування)

Жодне з них не є концепціями ООП. Всі вони існують за межами ОО, незалежні від ОО, і багато навіть були винайдені перед ОО.

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

Наприклад, одна з наглядових робіт про модульність - про критерії, які слід використовувати у розкладанні систем на модулі . Там немає згадки про ОО. (Це було написано в 1972 році, тодішній ОО ще був незрозумілою нішею, незважаючи на те, що йому вже було більше десяти років.)

Хоча абстракція даних є важливою для ОО, вона є скоріше наслідком первинної ознаки ОО (обміну повідомленнями), ніж визначальною. Також дуже важливо пам’ятати, що існують різні види абстрагування даних. Два найпоширеніші види абстрагування даних, які використовуються сьогодні (якщо ми ігноруємо "ніякої абстракції", яка, ймовірно, все ще використовується більше, ніж інші дві комбіновані), - це абстрактні типи даних та об'єкти . Отже, просто кажучи «Приховування інформації», «Інкапсуляція» та «Абстракція даних», ви нічого не сказали про ОО, оскільки ОО є лише однією формою абстрагування даних, а дві фактично принципово різні:

  • При абстрактних типах даних механізмом абстракції є система типів ; саме система типів приховує реалізацію. (Система типів не обов'язково повинна бути статичною.) З об'єктами реалізація прихована за процедурним інтерфейсом , який не потребує типів. (Наприклад, він може бути реалізований із закриттями, як це робиться в ECMAScript.)
  • Завдяки абстрактним типам даних екземпляри різних ADT інкапсульовані один від одного, але екземпляри одного ADT можуть перевіряти та отримувати доступ до представництва та приватної реалізації інших. Об'єкти завжди капсульовані від усього . Тільки об'єкт сам може перевірити своє власне представництво і доступ до власним реалізації. Жоден інший об'єкт , навіть інші об'єкти одного типу, інші екземпляри одного класу, інші об'єкти, що мають той самий прототип, клони об'єкта або що-небудь інше. Немає .

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

В основному для типів можна використовувати лише інтерфейси. Це означає, що типи параметрів методів та конструкторів, типи повернень методів, типи полів екземплярів, статичні поля та локальні поля, аргумент instanceofоператору чи оператору керування та аргументи типу для конструктора загального типу завжди повинні бути інтерфейсами. Клас може використовуватися лише безпосередньо після newоператора, ніде більше.

Наприклад, для модульності ми можемо просто розділити програму на багато невеликих програм, які виконують чітко визначені завдання, код яких міститься в окремих файлах. Ці програми взаємодіють одна з одною через їх чітко визначений вхід та вихід. Файли можуть бути захищені (зашифровані?) Для досягнення інкапсуляції. Для повторного використання коду ми можемо просто викликати ці файли, коли вони знадобляться в нових програмах. Хіба це не охоплює все, що є OOP, або я пропускаю щось дуже очевидне?

Те, що ви описуєте, є ОО.

Це дійсно хороший спосіб подумати про ОО. Насправді, це саме те, що мали на увазі оригінальні винахідники ОО. (Алан Кей пішов на крок далі: він передбачив безліч маленьких комп'ютерів, що надсилають повідомлення один одному через мережу.) Те, що ви називаєте "програмою", зазвичай називають "об'єктом", а замість "дзвінка" ми зазвичай кажемо "надішліть повідомлення ".

Об'єктна орієнтація стосується Повідомлень (також динамічної диспетчеризації ). Термін "Орієнтований на об'єкт" був введений доктором Аланом Кей, головним дизайнером Smalltalk, і він визначає це так :

OOP для мене означає лише обмін повідомленнями, локальне збереження та захист та приховування державно-процесу, а також надзвичайне запізнення всіх речей.

Розберемо це:

  • обмін повідомленнями ("віртуальний метод відправки", якщо ви не знайомі з Smalltalk)
  • державний процес повинен бути
    • локально зберігається
    • захищені
    • приховано
  • крайнє пізнє зв’язування всіх речей

По мірі впровадження, обмін повідомленнями - це запізнілий виклик процедури, і якщо виклики процедури запізніли, то ви не можете знати в час проекту, що ви збираєтесь викликати, тому ви не можете робити жодних припущень щодо конкретного подання стану. Отже, насправді мова йде про обмін повідомленнями, пізнє зв’язування - це реалізація повідомлень, а інкапсуляція є наслідком цього.

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

Лише ніжне нагадування про те, що я взяв певні болі на останньому OOPSLA, щоб спробувати нагадати всім, що Smalltalk - це не лише НЕ його синтаксис чи бібліотека класів, мова навіть не про класи. Мені шкода, що я давно придумав для цієї теми термін «об’єкти», оскільки це змушує багатьох людей зосередитися на меншій ідеї.

Велика ідея - це "обмін повідомленнями" - саме про це і полягає ядро ​​Smalltalk / Squeak (і це те, що ніколи не було завершено в нашій фазі Xerox PARC). У японців є невелике слово - ma - для "того, що знаходиться між ними" - можливо, найближчий англійський еквівалент "interstitial". Ключове значення у створенні чудових та розростаючих систем - це набагато більше, щоб розробити те, як його модулі спілкуються, а не якими мають бути їх внутрішні властивості та поведінка. Подумайте про Інтернет - щоб жити, він (а) повинен дозволити багато різних ідей та реалізацій, що виходять за межі будь-якого єдиного стандарту, і (b) дозволяти різного ступеня безпечної взаємодії між цими ідеями.

(Звичайно, сьогодні більшість людей навіть не зосереджуються на предметах, а на заняттях, що ще більше неправильно.)

Повідомлення є основним для ОО як метафори, так і як механізму.

Якщо ви надіслаєте комусь повідомлення, ви не знаєте, що вони з ним роблять. Тільки річ , яку ви можете спостерігати, їх відповідь. Ви не знаєте, чи обробляли вони повідомлення самостійно (тобто, якщо об'єкт має метод), чи пересилали повідомлення комусь іншому (делегування / надання доступу), якщо вони навіть розуміли його. Ось в чому полягає інкапсуляція, ось про що йдеться ОО. Ви навіть не можете відрізнити проксі від реального, якщо він відповідає, як ви цього очікуєте.

Більш "сучасним" терміном "обмін повідомленнями" є "динамічне відправлення методу" або "віртуальний виклик методу", але це втрачає метафору і фокусується на механізмі.

Отже, є два варіанти визначення визначення Алана Кей: якщо ви дивитесь на це самостійно, ви можете помітити, що повідомлення в основному є запізненням виклику процедури, а пізнє зв'язування передбачає інкапсуляцію, тому ми можемо зробити висновок, що №1 і №2 насправді надлишкові, і OO - все про пізнє зв’язування.

Однак пізніше він уточнив, що важливою справою є обмін повідомленнями, і тому ми можемо дивитись на це з іншого кута: обмін повідомленнями запізнюється. Тепер, якби обмін повідомленнями був єдиним можливим, то №3 тривіально відповідає дійсності: якщо є лише одне, а ця річ є пізньою, то всі речі запізнілими. І ще раз, інкапсуляція випливає з обміну повідомленнями.

Подібні пункти також зроблені в On Розуміння даних абстракцією, Revisited по Вільям Р. Кук , а також його пропозиція щодо спрощення, сучасні визначення «об'єкта» і «об'єктно - орієнтованого» :

Динамічна відправка операцій є істотною характеристикою об'єктів. Це означає, що операція, яку слід викликати, є динамічною властивістю самого об'єкта. Операції неможливо ідентифікувати статично, і взагалі немає способу [знати], що саме виконає операція у відповідь на заданий запит, за винятком її виконання. Це точно так само, як і з першокласними функціями, які завжди динамічно розсилаються.

У Smalltalk-72 навіть об’єктів не було! Були лише потоки повідомлень, які були розібрані, переписані та перепрограні. Спочатку з'явилися методи (стандартні способи розбору та перенаправлення потоків повідомлень), пізніше з'явилися об'єкти (групування методів, які поділяють деякий приватний стан). Успадкування з'явилося набагато пізніше, і заняття були запроваджені лише як спосіб підтримки спадщини. Якби дослідницька група Кей вже знала про прототипи, вони, ймовірно, ніколи б не вводили заняття в першу чергу.

Бенджамін Пірс у типах та мовах програмування стверджує, що визначальною особливістю об'єктно-орієнтованої діяльності є відкрита рекурсія .

Отже: за словами Алана Кей, OO - все про обмін повідомленнями. За словами Вільяма Кука, OO полягає в диспетчеризації динамічних методів (це дійсно те саме). За словами Бенджаміна Пірса, все стосується відкритої рекурсії, що в основному означає, що самонавіювання динамічно вирішується (або, принаймні, це спосіб задуматися), або, іншими словами, повідомленнями.

Як бачите, людина, яка ввела термін "ОО", має досить метафізичний погляд на об'єкти, Кук має досить прагматичний погляд, а Пірс - дуже суворий математичний погляд. Але важливо: філософ, прагматик і теоретик всі згодні! Повідомлення - це один стовп ОО. Період.

Зауважте, що тут не йдеться про спадщину! Спадкування не є важливим для ОО. Загалом, більшість мов OO мають певний спосіб повторного використання, але це не обов'язково має бути спадком. Наприклад, це може бути якась форма делегування. Насправді, Орландоський договір обговорює делегування як альтернативу успадкування та те, як різні форми делегування та спадкування призводять до різних пунктів дизайну в просторі дизайну об'єктно-орієнтованих мов. (Зауважте, що насправді навіть мовами, які підтримують успадкування, як, наприклад, Java, людей насправді вчать уникати цього, знову ж таки вказуючи, що це не потрібно для ОО.)


16
+100 - Ми ставимо вину на речі, оскільки вони неправильно використовуються.
JeffO

55
Вибачте, але це так неймовірно неправильно. Алан Кей, можливо, придумав цей термін, але принципи існували раніше у Smalltalk. Об'єктно-орієнтоване програмування походить від Simula, і його стиль OO не має нічого спільного з "повідомленнями". Практично кожна успішна мова OO працює на основних принципах, викладених у Simula - тих самих, які ми бачимо на Java - і OO у стилі Smalltalk зазнала невдачі на "ринку ідей" щоразу, коли її знову вводили, тому що це зовсім не дуже добре працює. Назва була єдиною справді значущою справою, яку сприяв Кей.
Мейсон Уілер

23
@steakexchange № "Суть ОО", що робить його справді відмінним, - це об'єкти з віртуальними методами. Існує причина, що ніхто не використовує Smalltalk: система передачі повідомлень працює дуже погано на індивідуально-комп’ютерних масштабах. Кожен раз, коли якийсь навмисний, але наївний мовний дизайнер намагається реалізувати принципи Smalltalk, це закінчується невдачею. (Найновішим прикладом може бути «Objective-C», який ніхто б ніколи не використовував, якби Стів Джобс не збив би його за всю горло спільноти iOS. Він ніколи не виявив жодної тяги поза екосистемою Apple, і в цьому є причина. )
Мейсон Уілер

28
@MasonWheeler Чи можете ви, можливо, детальніше пояснити свій коментар у відповіді, оскільки у вас є протилежний погляд на те, що говорить Йорг?
steakexchange

20
Варто також зазначити, що концепція об'єктно-орієнтованих мов розвивалася дуже багато. Ці предкові концепції в даний час можуть бути не такими справжніми, коли багато мов ухиляються від старих моделей і містять багато парадигми. Наприклад, погляньте на C # - що мова змішує майже все під сонцем одразу, і, в основному, називається мовою ОО, це фактично поєднання різних парадигм. Це дає змогу стати дійсно виразним інструментом для розробників навколо. Крім того, клас на базі класу є одним з багатьох не менш вагомих ароматів програмування ОО.
Т. Сар

66

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

Коли ви говорите "дуже легко", ви робите дуже сміливе твердження. Я прочитав це: "Я не бачу труднощів, тому він не повинен бути дуже великим". Коли ви поставите фразу таким чином, стає зрозуміло, що ви не запитуєте "навіщо нам потрібна ОО", ви запитуєте "чому мені не очевидні труднощі, з якими стикаються інші парадигми програмування, які призводять до винаходу ОО?" "

Відповідь на це питання полягає в тому, що багато з цих труднощів не існують у видах програм, над якими ви працюєте. Вас не просять оновити 40-річний код спагетті. Ви не намагаєтесь написати новий менеджер дисплеїв для операційної системи. Ви не налагоджуєте багатопотокові розповсюджені програми.

Для багатьох видів іграшкових програм, з якими ми навчаємось студентам CS, ми можемо так само добре писати їх у BASIC або збирати як Java або Python. Це тому, що притаманна складність завдань настільки низька, є лише один розробник, немає ніяких застарілих проблем інтероперабельності, продуктивність не має значення, і код, ймовірно, коли-небудь буде виконуватися кілька разів на одній машині.

Уявіть, як взяти студентського водія і попросити їх з'їхати на зайняту вулицю в годину пік, на ручній коробці передач без синхромеша, прямуючи вгору по крутій горі. Катастрофа. Чому? Вони не в змозі керувати рівнем складності, необхідним для одночасного дотримання всіх правил, яких вимагає завдання.

А тепер уявіть, що той самий студент, той самий транспортний засіб, їздить у пішому темпі на порожній парковці. Вони в порядку, оскільки рівень їх майстерності адекватний завданню. Немає тиску, мало ризику, і вони можуть приймати окремі підзадачі пуску, зчеплення, перемикання, прискорення, керування одна за одною.

Цей студент може запитати, чому ми маємо автоматичні трансмісії, якщо досвідчений водій може робити все це одночасно? Відповідь полягає в тому, що достатньо кваліфікований водій в оптимальних умовах не потребує автоматики. Але ми не всі професійні водії у піковому стані, і ми, як правило, хочемо зручності того, щоб дизайнери автомобілів подбали про всю цю складність для нас.

Кваліфікований, достатньо дисциплінований програміст дійсно може створити функціонуючу систему високої складності в С або збірці. Але ми не всі Лінус Торвальдс. Ми також не повинні бути для створення корисного програмного забезпечення.

Я особисто не маю зацікавленості в тому, щоб винаходити всі риси сучасної мови, перш ніж я зможу вирішити проблему. Якщо я можу скористатися мовою, яка включає рішення вже вирішених проблем, чому б я не став?

Тож я переверну ваше запитання і запитаю вас, якщо мови надають зручні функції, такі як інкапсуляція та поліморфізм, чому б нам не використовувати їх?


13
Таким чином, в основному можна робити OO процедурною мовою, але це робиться вручну, використовуючи стандартизовану мову OO, автоматизує та спрощує.
steakexchange

6
@steakexchange Досить точно.
Тім Б

3
@steakexchange хорошим історичним прикладом цього стала об'єктна модель для X Windows ще в той час. Він був написаний на С, але базувався на об'єктно-орієнтованій системі. Отже, вам довелося дотримуватися певних умов, щоб взаємодіяти з ним, щоб ваші заняття добре грали з усіма іншими.
Укко

7
@nocomprende Безумовно. Але можна зробити комп'ютер незавантаженим, виконуючи записи із сирої дискової системи замість того, щоб покладатися на файлову систему, і буде справді важко налагодити проблеми в спеціальній об’єктній системі, побудованій новачком. Якщо правильно виконати інкапсуляцію, ми не можемо навмисно чи ненавмисно втручатися в речі, які ми не повинні.
Климент Черлін

3
Мені цікаво, що приклади, які ви наводите із заявок, які б виграли від ОО, часто не пишуться мовами ОО. 40-річні спагетті, ймовірно, написані на C, COBOL, FORTRAN або REXX. Диспетчер дисплеїв, ймовірно, написаний на С (хоч і з умовами OO-ish), і багато успішних розподілених багатопотокових систем написано в Erlang, Go або C.
James_pic

22

Те, що ви описуєте, не є ООП, це абстракція. Абстракція присутня у всіх сучасних моделях дизайну, навіть у тих, що не є OOP. І ООП - це дуже специфічний вид абстракції.

По-перше, варто зазначити, що немає єдиного визначення OOP, тому можуть бути люди, які не згодні з тим, що я характеризую як OOP.

По-друге, важливо пам’ятати, що OOP був натхненний традиційними моделями дизайну, тому подібність з дизайном автомобіля не випадкова.

Однак ось декілька способів OOP є більш нюансованим, ніж те, що ви сказали:

  • Інкапсуляція: мова йде не лише про встановлення інтерфейсу для модуля (тобто абстрагування), а про заборону доступу поза цим інтерфейсом. У Java доступ до приватної змінної є помилкою компіляції, тоді як у дизайні вашого автомобіля ви можете (в деяких випадках) використовувати речі таким чином, що відрізняється від призначеного інтерфейсу.

  • Спадщина: Це дійсно те, що робить OOP унікальним. Визначивши інтерфейс, ви можете зробити кілька речей, що реалізують цей інтерфейс, і це можна зробити герархічно, змінюючи конкретні частини їх реалізації, успадковуючи при цьому всі попередні частини, масово зменшуючи дублювання коду.

    Якщо ви думаєте з точки зору інкапсульованих компонентів автомобіля, це насправді не еквівалент цьому. Немає способу зробити передачу, взявши іншу передачу та змінивши певну частину її виконання. (Принаймні, я не думаю, що про машини я не знаю багато).

  • Поліморфізм . Після того, як ви визначили інтерфейс, все, що використовує цей інтерфейс, повинно бути нерозрізненим з точки зору того, які операції доступні, і вам не потрібно знати, яка реалізація використовується для використання інтерфейсу. Саме тут важливе значення мають підтипи та принцип заміщення Ліскова .

  • З'єднання : Ключовим аспектом OOP є те, що ми тісно пов’язуємо речі з одними і тими ж операціями та розповсюджуємо різні форми, які вони можуть мати. Дані поєднуються з операціями над цими даними. Це означає, що додати нову форму даних (нова реалізація) дуже просто, але дуже складно додати нову операцію в інтерфейс (оскільки вам доведеться оновлювати кожен клас, який реалізує інтерфейс). Це на відміну від алгебраїчних типів даних у функціональних мовах, де додати нову операцію дуже просто (ви просто пишете функцію, яка займається всіма випадками), але важко додати новий варіант (оскільки вам потрібно додати новий залежно від усіх ваших функцій).


1
Хороша відповідь! Одну частину, з якою я не згоден: відмінність, яку ви робите щодо інкапсуляції, не вірна. Інкапсуляція завжди означає "забороняти доступ за межі цього інтерфейсу" - це справедливо і для налаштувань OOP, і для не-OOP. Тож ця частина насправді не є унікальною для OOP.
DW

@DW Я намагався уточнити це, кажучи не про те, що це унікальне для OOP, але що це різниця між інкапсуляцією та абстракцією. Дякуємо за відгук!
jmite

2
ГАРАЗД. Але я все ще маю інший погляд на те, що тут написано з цього приводу. Ви писали, що "ось деякі способи OOP є більш нюансованими, ніж те, що ви сказали", але інкапсуляція - це не такий спосіб, що OOP є більш нюансованим, ніж те, що було написано в питанні. Інкапсуляція - це те, що вона є, в будь-якій парадигмі. І там, де ви писали, що "Те, що ви описуєте, не є ООП, це абстракція", я подумав, що оригінальне питання намагається описати інкапсуляцію (не лише абстракцію). Я думаю, що я просто залишу цей коментар як інший погляд. Я думаю, що відповідь дуже корисна!
DW

Спадкування - це загальна особливість, але у деяких важливих мовах ОО не вистачає.
Бредд Шоні

Хороша відповідь, але IMO ви завищуєте приклад автомобіля. Двигун для даної моделі має чітко визначений інтерфейс (кулачковий вал, кріплення кронштейна "ємності" тощо). Можна замінити звичайний старий карбюратор на паливний, додати турбо-зарядний пристрій тощо, не впливаючи на трансмісію. (Хоча для дизельного двигуна потрібен модифікований паливний бак IIRC.) І навпаки, ви можете замінити ручну коробку передач на автоматичну та AFAIK, яка зовсім не впливає на двигун.
Давид

11

Чи справді нам потрібні мови ОО для управління складністю програмного забезпечення?

Це залежить від значення слова "потреба".

Якщо "потреба" означає, що вимагає, ні ми цього не вимагаємо.

Якщо "потреба" означає "забезпечує сильні вигоди", то я б сказав: "Так", ми цього бажаємо.

Велика картина

Мови ОО пов'язують функціональність з даними.

Ви можете уникнути цієї функції прив'язки та запису, яка передає значення даних.

Але тоді ви, ймовірно, закінчитеся сузір’ями даних, які збираються разом, і ви почнете обходити кортежі, записи чи словники даних.

І справді, це все виклики методів: часткові функції на зв'язаних наборах даних.

Особливість за особливістю

Особливості OOP:

  • Спадщина дозволяє повторно використовувати код (міксин) та концепцію (абстрактні базові класи / інтерфейси), але ви можете отримати це шляхом перевстановлення функцій та змінних у підрозділ.
  • Інкапсуляція дозволяє приховувати інформацію, тому ми можемо працювати на більш високих рівнях абстрагування, але ви можете зробити це за допомогою заголовкових файлів, функцій та модулів.
  • Поліморфізм дозволяє нам використовувати аргументи різних типів, якщо ці аргументи підтримують однакові інтерфейси - але ми можемо це робити і з функціями.

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

Список літератури

Є багато критиків ООП .

Однак дослідження, схоже, вказують на те, що ми отримуємо більшу продуктивність програміста від повторного використання коду через OOP. Це суперечливе висновок, і деякі дослідники стверджують, що не можуть відтворити ці підвищення продуктивності, враховуючи певні обмеження.(джерело)

Висновок

Ми не потребуємо "OOP". Але в деяких випадках користувач хоче OOP.

Я розумію, що зрілі програмісти можуть бути досить продуктивними в об'єктно-орієнтованому стилі. І коли у пакунків є основні об'єкти з простими інтерфейсами, які легко зрозуміти, навіть нові програмісти можуть швидко стати досить продуктивними.


10

Я спробую бути короткою.

Основним принципом ОО є поєднання даних і поведінки в єдиному організаційному підрозділі (об'єкті).

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

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

Отже, так, ОО - це велика справа. І ні, це не просто купа старих речей з вигадливою назвою.

Якщо розібрати все це, поглянувши на елементи, а потім сказати "о, ну, нічого тут я ще не бачив", це не визнати збірку, яка є інновацією. Результат більший, ніж сума його частин.


8

Не існує «офіційного» визначення об’єктно-орієнтованого програмування, і розумні люди не згодні з тим, що насправді визначає якість ОО. Деякі кажуть, що обмін повідомленнями, дехто говорить про підгрупування, деякі кажуть про спадщину, деякі кажуть, що згрупування даних та поведінки. Це не означає, що цей термін є безглуздим, просто ви не повинні занадто захоплюватися переслідуванням того, що таке справжній ОО.

Інкапсуляція та модульність є більш фундаментальними принципами дизайну, і їх слід застосовувати у всіх парадигмах програмування. Прихильники ОО не стверджують, що ці властивості можна досягти лише з ОО - лише те, що ОО особливо добре підходить для досягнення цього. Звичайно, прихильники інших парадигм, як, наприклад, функціональне програмування, стверджують те саме, що і їх парадигма. На практиці багато успішних мов є мульти-парадигмою, і ОО, функціональні тощо слід розглядати як інструменти, а не "єдиний справжній шлях".

Я думаю, що всі принципи управління складністю можуть бути реалізовані процедурними мовами програмування.

Правда, адже врешті-решт ви можете зробити що завгодно на будь-якій мові програмування. У деяких мовах це може бути простіше, ніж в інших, оскільки всі мови мають різні сильні та слабкі сторони.


7

Щось, що інші відповіді не згадували: держава.

Ви говорите про ОО як інструмент управління складністю . У чому складність? Це нечіткий термін. У всіх нас є гештальт, що це означає, але важче це визначити. Ми могли б виміряти цикломатичну складність, тобто кількість шляхів пробігу через код, але я не знаю, про що ми говоримо, коли використовуємо ОО для управління складністю.

Те, про що я думаю, ми говоримо про складність держави.

За інкапсуляцією стоять дві основні ідеї . Одна з них, приховування деталей реалізації , досить добре висвітлена в інших відповідях. Але інший приховує свій стан виконання . Ми не переймаємось внутрішніми даними об'єктів; ми передаємо повідомлення (або методи виклику, якщо ви віддаєте перевагу деталізації реалізації над концепцією, як вказував Йорг Міттаг). Чому?

Люди вже згадували це тому, що ви не можете змінити внутрішню структуру своїх даних, не змінивши код, який має доступ, і ви хочете зробити це в одному місці (метод accessor) замість 300 місць.

Але це також тому, що це робить код важко міркувати : процесуальний кодекс (будь то в мові, що має процедурний характер, або просто написаний у такому стилі) мало допомагає накладати обмеження на мутацію держави. Все можна змінити в будь-який час з будь-якого місця. Функції / методи виклику можуть мати жахливу дію на відстані. Автоматизоване тестування складніше, оскільки успішність тестів визначається значенням нелокальних змінних, які широко доступні / доступні.

Інші дві великі парадигми програмування (ОО та функціональні) пропонують цікаві, але майже діаметрально протилежні рішення проблеми складності, пов'язаної із станом. У функціональному програмуванні намагаються повністю цього уникнути: функції, як правило, чисті, операції над структурами даних повертають копії, а не оновлення оригіналу на місці тощо.

OO, з іншого боку, пропонує інструменти для управління станом (замість інструментів для його уникнення). На додаток до таких інструментів на мовному рівні, як модифікатори доступу (захищені / публічні / приватні), геттери та сетери тощо, існує також ряд споріднених конвенцій на зразок Закону про деметер, який радить не досягати через об'єкти отримання даних про інші об'єкти .

Зауважте, що вам не потрібні об'єкти, щоб робити щось із цього: ви можете мати закриття, яке має недоступні дані, і повертає структуру даних функцій для управління ними. Але це не об’єкт? Чи це не відповідає нашому уявленню про те, що є об'єктом, інтуїтивно? І якщо у нас є ця концепція, чи не краще переробити її на мові, а не (як говорили інші відповіді), спираючись на комбінаторний вибух конкуруючих спеціальних реалізацій?


5

Чи справді нам потрібні мови ОО для управління складністю програмного забезпечення?

Ні. Але вони можуть допомогти у багатьох ситуаціях.

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

Наприклад, програма Windows, що використовує оригінальний API Windows для низького рівня для відображення форми, кнопки та поля редагування, потребує великого коду, тоді як натомість використання бібліотек об’єктів, що постачаються з Visual Basic або C # або Delphi, роблять те саме програма крихітна і банальна. Отже, мій код OO, як правило, порівняно невеликий і для графічного інтерфейсу, тоді як мій код, який викликають ці об’єкти, як правило, набагато більший і зазвичай не пов'язаний з тим, що він є OO (хоча він може змінюватися залежно від проблеми, яку я намагаюся вирішити).

Я бачив програми OO, які були надмірно складними, спиралися на складні езотеричні правила щодо того, як об’єкти реалізовуються, і могли бути набагато простішими, якби писати без понять OO. Я також бачив протилежне: складні системи, що плачуть, повторюються та спрощуються за допомогою об'єктів.

Отримавши досвід, ви побачите, що різні ситуації потребують різних інструментів та рішень, а один розмір підходить не всім.


3

Оскільки хтось, хто бере участь у дуже великому проекті, повністю написаному на С, я точно можу сказати, що відповідь - це чітке "ні".

Модульність важлива. Але модульність може бути реалізована практично на будь-якій гідній мові. Наприклад, C підтримує модульну компіляцію, файли заголовків та типи структур. Цього достатньо для 99% випадків. Визначте модуль для кожного нового потрібного абстрактного типу даних та визначте функції для роботи над типом даних. Іноді ви хочете, щоб продуктивність і ці функції були у файлі заголовка як вбудовані функції, в інший раз ви використовуєте стандартні функції. Користувачеві все непомітно, який спосіб обраний.

Структури підтримують композицію. Наприклад, у вас може бути заблокована хеш-таблиця, яка складається з mutex lock та звичайної хеш-таблиці. Це не об’єктно-орієнтоване програмування; ніяке підкласифікація не робиться. Композиція - це засіб, набагато старший за ідею об'єктно-орієнтованого програмування.

У 1% випадків, коли модульність рівня компіляції недостатня, і вам потрібна модульність виконання, існує річ, яка називається функціональними покажчиками. Вони дозволяють мати індивідуальні реалізації чітко визначеного інтерфейсу. Зауважте, що це не об'єктно-орієнтоване програмування не об'єктно-орієнтованою мовою. Це визначення інтерфейсу, а потім його реалізація. Наприклад, тут не використовується підкласифікація.

Розглянемо, мабуть, найскладніший проект з відкритим кодом. А саме ядро ​​Linux. Він написаний повністю мовою С. Це робиться головним чином за допомогою стандартних інструментів модульності рівня компіляції, включаючи композицію, а потім періодично, коли потрібна модульність виконання, функціональні покажчики використовуються для визначення та реалізації інтерфейсу.

Якщо ви спробуєте знайти приклад об’єктно-орієнтованого програмування в ядрі Linux, я впевнений, що знайти такий приклад дуже важко, якщо ви не розширите об'єктно-орієнтоване програмування на такі стандартні завдання, як "визначення інтерфейсу та його реалізація".

Зауважте, що навіть мова програмування C підтримує об'єктно-орієнтоване програмування, якщо воно вам справді потрібне. Наприклад, розглянемо графічний набір інструментів користувальницького інтерфейсу GTK. Це насправді об'єктно-орієнтоване, хоч і написане не об’єктно-орієнтованою мовою. Отже, це свідчить про те, що думка про те, що вам потрібна "об'єктно-орієнтована мова", є глибокою помилкою. Немає об'єктно орієнтованої мови, що не може зробити інший вид мови. Крім того, якщо ви досвідчений програміст, ви знаєте, як написати об'єктно-орієнтований код на будь-якій мові дуже легко. Наприклад, використання C не є тягарем.

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


1
"[...] висновки полягають у тому, що об'єктно-орієнтовані мови, ймовірно, корисні лише початківцям програмістам, які не розуміють, як реально реалізується концепція." Цікаво. Які мови ви маєте на увазі? Чи є у вас приклади проектів з відкритим кодом, написаними цими мовами, які не вдалися або не вийшли з ладу?
Вінсент Савард

3
Ви піднімаєте кілька хороших балів, але ваша основна ідея є хибною. Так, можна реалізувати такі концепції OO, як інкапсуляція, віртуальна відправка, успадкування і навіть вивезення сміття такою мовою, як C. Це також можна зробити в зборах. Це не спрощує програмування. Програмування та, особливо, проектування на такій мові, як C, безумовно, складніше, ніж у мові ОО. На мові C потрібно зіставити концепції для їх реалізації, мовою ОО не потрібно робити цей крок (принаймні, не для концепцій ОО).
риболовлю

1
"[покажчики функцій] дозволяють мати індивідуальні реалізації чітко визначеного інтерфейсу. Зауважте, що це не об'єктно-орієнтоване програмування не об'єктно-орієнтованою мовою. Це визначення інтерфейсу, а потім його реалізація." Вибачте, але це абсолютно неправильно, адже саме це є OOP. "Наприклад, тут не використовується підкласифікація" Підкласифікація не є обов'язковою особливістю OOP. Зауважте, наприклад, що JavaScript - це об'єктно-орієнтована мова, яка не містить підкласи (або, з цього приводу, класи взагалі ... Просто об'єкти, що містять посилання на функції).
Жуль

1
Для уточнення мого останнього коментаря, моя думка полягає в тому, що головним відмінним фактором між OOP (не обов'язково будь-якою конкретною мовою OO) та іншими методами є те, що в OOP ми визначаємо інтерфейси, які оперують абстрактними даними, не знаючи формат цих даних за прив’язування реалізації інтерфейсів до самих даних. Це те, що є ООП. Спосіб реалізації не має значення, чи це клас стилю Java, об’єкт JavaScript (фактично карта імен для атрибутів, яка може бути або даними, або кодом) або структура, що містить покажчики функцій та порожнечу * даних.
Жуль

1
"Отже, висновки полягають у тому, що об'єктно-орієнтовані мови, ймовірно, корисні лише початківцям програмістам, які не розуміють, як реально реалізується концепція." .... І це, чесно кажучи, явно ображає. Я досить добре знаю, як ці концепції реалізуються. Я зробив достатньо роботи, використовуючи тоді, щоб бути досвідченим навіть. У минулому я навіть впроваджував і перекладач, і компілятор для мов ОО. Але оскільки я вважаю за краще працювати на мовах вищого рівня, які мають об'єкти першого класу, я повинен бути початківцем програмістом, з яким ви б краще не працювали ?!
Жуль

2

Причиною введення парадигм програмування, включаючи об’єктно-орієнтовані методи, є полегшення створення більш досконалих та потужних програм. У серпневому випуску журналу "Байт" за серпень 1981 року Даніель Інгеллз , один з ключових творців Smalltalk, визначив "об'єктно-орієнтовану", що передбачає такі можливості:

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

Це були принципи, які Інгаллс визначив як основні роздуми щодо проекту SmallTalk-80, розробленого Xerox Parc Research. У вищезгаданій статті журналу ви можете прочитати детальний опис кожного з цих принципів та того, як вони сприяють об'єктно-орієнтованій парадигмі згідно з Інґаллсом.

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

Наприклад, щоб взяти перший з принципів Ingall (автоматичне управління зберіганням), кожен може написати власну систему автоматичного управління пам’яттю процедурною мовою, але для цього було б дуже багато роботи. Під час використання такої мови, як SmallTalk або Java, яка має вбудоване автоматичне управління пам’яттю, програмісту не доведеться робити стільки роботи з управлінням пам’яттю. Компроміс полягає в тому, що програміст отримує менший контроль над тим, як використовується пам'ять. Отже, є користь і недолік. Ідея такої парадигми дизайну, як об'єктно-орієнтоване програмування, полягає в тому, що переваги парадигми переважають за недоліки принаймні деяких програмістів.


Я думаю, що ті ж правила застосовуватимуться і у випадку мов, що визначаються конкретним доменом. Ті ж переваги та недоліки ... Єдина відмінність полягає в тому, що DSL можна зробити досить простими для роботи кінцевих користувачів, оскільки "мова" відповідає їхньому розумінню проблемного простору, і більше нічого не включається.

0

Одним із способів управління складністю програмного забезпечення є відокремлення рамки від бажаних дій, повністю за допомогою мови, що визначає домен . Це означає, що рівень коду програмування відрізняється від рівня, на якому налаштовані бажані результати - зовсім інша мова чи система. Якщо це зроблено належним чином, звичайний код по суті стає бібліотекою, і користувач або інша особа, яка створює потрібні результати, підключає речі разом із мовою сценаріїв або засобом візуального дизайну, наприклад генератором звітів.

Для роботи для цього потрібно провести чітку межу навколо того, які операції будуть можливі та як вони зв’язуються (мова сценарію чи візуальний дизайн, як інструмент побудови форми). Метадані є важливим способом вилучення конфігурації часу виконання від деталей кодування, завдяки чому система може підтримувати широкий спектр бажаних результатів. Якщо межі встановлені і дотримуються (не приймаючи кожного запиту на продовження, що йде разом), ви можете мати довговічну і надійну систему, яка працює для людей, без них не потрібно бути програмістами, щоб досягти того, що вони хочуть.

Про це Мартін Фаулер написав книгу, а методика майже така ж стара, як і саме програмування. Ви майже можете сказати, що всі мови програмування - це мови, які є специфічними для домену, і тому ідея є ендемічною, не поміченою, оскільки вона така очевидна. Але ви все одно можете створити власні інструменти для створення сценаріїв або візуального дизайну, щоб полегшити своє життя. Іноді узагальнення проблеми полегшує вирішення!


0

Це дуже гарне запитання, і я вважаю, що відповіді, надані тут, не справедливі, тому я продовжую і додаю свої думки.

Мета - Управління складністю програмного забезпечення . Метою є не «використання мови ОО».

Це не є причиною для введення нової парадигми. Це трапилося природним чином, коли кодування стало більш зрілим. Більш сенс писати код, коли ми додаємо вагон в кінці поїзда (поїзд моделюється за допомогою пов'язаного списку), а не додавати новий вузол до кінця пов'язаного списку.


Кодування в термінах реальних об'єктів просто очевидний і правильний спосіб кодування , коли ми є кодування про реальні об'єкти.


Комп'ютер може працювати з додаванням вузла до кінця зв'язаного списку так само легко, як це може працювати з додаванням додаткового тренера до кінця поїзда. Але людям легше працювати з поїздом і поїздом, ніж із пов'язаним списком і вузлами, навіть коли ми йдемо на глибину рівня, ми виявляємо, що поїзд моделюється за допомогою пов'язаного списку.

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

Отже, ви можете написати код, який є зашифрованим і добре інкапсульованим, оскільки ці два різні поняття.

Інкапсуляція допомагає керувати складністю завдяки тому, що вона наближається до реальності.

Тому програмуйте в об'єктах, тому що вам простіше кодувати, і вам швидше зрозуміти вам і всім іншим.


0

Варто пам’ятати про це:
OOP - не про особливості мови; мова йде про те, як ви структуруєте свій код .

OOP - це спосіб мислення та розробки архітектури вашого коду, і це можна зробити практично будь-якою мовою. Особливо це стосується тих низькорівневих мов, що не належать до OO, які називаються ассемблером і C. Ви можете виконати ідеально об'єктно-орієнтоване програмування в асемблері, а ядро ​​Linux, яке написано на C, є цілком об'єктно-орієнтованим у багатьох аспектах. .

Зважаючи на це, функції OO на мові значно зменшують кількість кодової панелі, яку потрібно написати, щоб досягти бажаних результатів . Там, де вам потрібно чітко визначити віртуальну таблицю функцій та заповнити її відповідними покажчиками функцій на C, ви просто зробите нічого в Java, і ви все зробили. Мови OO просто видаляють все те, що дозволяє чітко виходити з вихідного коду, ховаючи його за приємними абстракціями на рівні мови (наприклад, класи, методи, члени, базові класи, неявні виклики конструктора / деструктора тощо).

Отже, ні, нам не потрібні мови OO, щоб робити OOP. Просто OOP так простіше зробити з гідною мовою ОО.


-1

Об'єктно-орієнтоване програмування - це більше, ніж просто модулі + інкапсуляція. Як ви кажете, можна використовувати модулі + інкапсуляція не об'єктно-орієнтованою (процедурною) мовою. OOP передбачає більше, ніж просто це: вона включає об'єкти та методи. Отже, ні, це не охоплює OOP. Див., Наприклад, https://en.wikipedia.org/wiki/Object-oriented_programming або хороший вступ підручника до OOP.


Дякую за відповідь. Не могли б ви порекомендувати його?
steakexchange

-2

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

Давайте уявимо систему з 100 класів, у кожному з яких приблизно 20 операцій, які можна виконати на них; це 2000 функцій. Однак з них, можливо, лише 500 - це завершені операції, такі як "Зберегти" та "Видалити", тоді як 1500 - це внутрішні функції, які виконують трохи технічного обслуговування або виконують певну корисність. Розглянемо;

// intentionally in a non-specific language!

setName(person, name) {
    nameParts = splitPersonName(name);
    person.firstName = nameParts[0];
    person.lastName = nameParts[1];
    person.modified = true;
}

splitPersonName(name) {
    var result = [];
    result.add(name.substring(0, name.indexOf(" ")));
    result.add(name.substring(name.indexOf(" ") + 1));
    return result;
}

Тому SetNameфункція люди повинні робити для людини, але SplitPersonNameце функція корисності використовується на людину.

Пряме процедурне програмування не відрізняє цих двох операцій. Це означає, що ваші 2000 функціональних усеохоплюють вашу увагу. Однак, якщо ми могли б позначити ці функції як "доступні всім, хто має запис про людину" і "використовуються лише як функції утиліти всередині запису про людину", то наша увага тепер 500 "доступна для всіх", а 15 - "корисність" функції для класу, який ви редагуєте.

Ось що publicі privateробити;

public class Person {
    public void setName(...) {...}
    private string[] splitPersonName(...) { ...}
}

1
Я не впевнений, чи правильно ви зрозуміли моє запитання. Мені вже відомі інкапсуляція та приховування даних як спосіб управління складністю. Я просто думаю, що це можна легко зробити і в процедурних мовах, поділивши програму на модулі, які виконують чітко визначені прості завдання, внутрішня робота яких визначена в окремих захищених джерелах. То чому б OOP, коли ми можемо робити це на процедурних мовах? Це моє запитання.
steakexchange

2
Я думаю, що моя відповідь полягає в тому, що якщо ви хочете зробити подібне, вам доведеться писати спеціальні інструментальні та мовні конструкції для цього (наприклад, спеціальний виклик "включити" для включення одного файлу, який може не включати в інше місце). Після того як ви почали цей шлях, ви фактично почали реалізовувати об'єктно-орієнтовану мову по-своєму. Наприклад, C ++ спочатку був препроцесором, який виробляв звичайний C , і я підозрюю, що коли ви впроваджуєте свою систему, це схоже на C ++ поверх C.
user62575

3
@steakexchange Зауважте, що OOP був розроблений час, коли багато процедурних мов не мали подібних модулів. Деякі навіть не називали б такі мови процедурними. Дійсно, нічого, що говорить про процедурну мову, не повинно бути ОО або навпаки. Будьте уважні до етикеток - вони можуть вас легко ввести в оману. Якщо ваша процедурна мова підтримує модулі, які мають публічні та приватні поля та процедури, вам корисна :) Основна відмінність "традиційних процедурних" від "OOP" полягає в тому, що відправлення викликів є більш гнучким в OOP - дійсно, в суворій OOP, ви ніколи не знаю, який код ви дзвоните.
Луань

2
@steakexchange У мовах сімейства ML дуже чудово працюють модулі, а в поєднанні з лямбдами вони надають всю силу будь-якої мови OO (адже функція - це інтерфейс з одним методом - чи не те, що рекомендується "хороший код" хлопці в ОО?: P). З різних причин вони все ще менш використовуються, ніж більш процедурні мови, такі як C ++ або Java, але вони мають свою привабливість, і багато людей намагаються навчити людей, як вони можуть спростити своє життя (з більш-менш успіхом).
Луань

C ефективно має ці речі. У ньому є модулі (.c файли) з інтерфейсами (.h файли), і він може мати публічні (екстерн) та непублічні (зовнішні) методи (функції). Ви навіть можете мати поліморфізм бідолахи з масивами функціональних покажчиків, я не кажу, що ОО легко в C (або, можливо, розумно), але інкапсуляція досить проста,
Нік Кейлі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.