Чи існують мови OO без успадкування?


22

Під час огляду коду сьогодні мій колега сказав щось цікаве:

prototypeкорисна лише тоді, коли вам потрібна спадщина - а коли спадщина колись гарна ідея ?

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

Чи існують мови програмування загального призначення з класами, об'єктами, методами, інтерфейсами тощо, які забороняють успадкування на основі класів? (Якщо така ідея не має сенсу, чому б і ні?)


7
Ваш колега заблудив вас. prototypeТакож корисно , якщо у вас є відкриті методи і властивості , які повинні бути розділені між екземплярами. Це також корисно , тому що дозволяє правильно використовувати instanceofоператор в JavaScript: if (foo instanceof Foo) { ....
Грег Бургхардт

2
Я думаю, що ми повинні розрізняти спадщину типу, стану та поведінки. Перевага складу дуже поширене в спільноті Java, але в той же час успадковування (і навіть багаторазове успадкування) типів широко використовується і заохочується ... і реалізується за допомогою implementsключового слова та інтерфейсів (на відміну від успадкування стану і поведінка, введена із використанням extendsключового слова в класах, що містять будь-яку реалізацію).
toniedzwiedz

6
Віддавати перевагу складу не означає повністю відмовитися від спадщини - це гарна ідея.
Калеб

5
див. Java без успадкування реалізації : "Google's go - це приклад мови, яка не дозволяє наслідувати реалізацію, будучи OOP ..."
gnat

1
@GregBurghardt Те ж саме можна виконати із заводською функцією, яка повертає об'єкт, що містить функції (зберігання приватних даних у закритті). new, thisі prototypeвсе це занадто багато мінного поля для загального використання ІМО.
Бенджамін Ходжсон

Відповіді:


18

Відміняючи питання щодо визначення об’єктно-орієнтованого програмування, питання стає однією з "чи існують мови, які використовують лише склад і не мають інструментів для успадкування?"

Відповідь на це досить просто «так». Зрештою, немає способу зробити спадщину так, як це думає класично. Один може впроваджений об'єкт в іншому об'єкті і продовжити цей об'єкт. З об'єкта дезорієнтованої мови ( дзеркало github ):

type Person struct {
        Name string
}

func (p *Person) Intro() string {
        return p.Name
}

type Woman struct {
        Person
}

func (w *Woman) Intro() string {
        return "Mrs. " + w.Person.Intro()
}

У вас є структура людини, яка має ім'я, яке є рядком. Він має публічну функцію під назвою Intro, яка повертає ім'я. Жіноча структура також має функцію для Intro, яка отримує доступ до вбудованої в неї стійки. І так можна здійснити наміри успадкування, використовуючи лише склад.

Більше про це можна побачити в підручниках GoLang: Спадництво та підкласифікація в Go - або його близькій подобі .

Так, так, можна мати мову OO без успадкування, і така існує.

У режимі go це відоме як вбудовування та надає структурам, що додають, можливість отримувати доступ до вбудованих полів та функцій так, ніби вони також їх мали, але це не підклас. Філософію дизайну можна знайти в FAQ FAQ: Чому не існує успадкування типу?


Можна також прокоментувати використання typedefта structв C ...
cwallenpoole

@cwallenpoole там дійсно схожі ідеї, хоча я б вагався назвати C об'єктно-орієнтованою мовою.

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

@cwallenpoole і ми починаємо визначати, що таке спадщина та орієнтація на об'єкт. Але це можливо, його просто інший спосіб думати про проблему. Вся справа в тому, що успадкування - це те, як більшість програмістів на C ++ та Java думають про розширення ... але є й інші моделі. Розширення без успадкування: 1 , 2 , 3 - це добрі читання.

Посилання на "Об'єктована дезорієнтована мова" наразі застрягла у циклі переспрямування, але я знайшов тут статтю: github.com/nu7hatch/areyoufuckingcoding.me/blob/master/content/… . Спасибі!
Метт Браун

7

Чи існують мови програмування загального призначення з класами, об'єктами, методами, інтерфейсами тощо, які забороняють успадкування на основі класів?

Це дуже схоже на опис VBA - Visual Basic для додатків, вбудований в Microsoft Office та інші VBA з підтримкою VBA (наприклад, AutoCAD, Sage 300 ERP тощо) або навіть VB6. "A" "Basic" так чи інакше означає "універсальний", тому є "загальна цільова" частина.

VB6 / VBA має класи (і, отже, об'єкти), методи та інтерфейси - ви можете визначити ISomethingінтерфейс у модулі класу на зразок цього:

Option Explicit

Public Sub DoSomething()
End Sub

А потім ще один клас, який робить це:

Option Explicit
Implements ISomething

Private Sub ISomething_DoSomething()
    'implementation here
End Sub

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

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

Якщо Go не займається успадкуванням класів і тим не менш є мовою OOP , я не розумію, чому VB6 / VBA також не може вважатися мовою OOP.</PreemptiveResponseToVBAHatersThatWillSayItIsNotAnOOPLanguage>


1
Для справедливості ОП запитала про сучасні мови. =;) -
RubberDuck

@RubberDuck #burn!
Матьє Гіндон

0

Ви можете змусити компілятор примусово виконувати вибіркове успадкування за допомогою використання приватних / захищених та сучасних методів використання "PImpl" або "Приватної реалізації".

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

Швидкий пошук функцій приватного члена в javascript показує, що існує подібний принцип, хоча кожен може побачити ваш код, якщо він може ним користуватися: http://www.crockford.com/javascript/private.html

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.