Якщо я реалізую інтерфейс, це називається спадщиною?


31

Якщо мій клас implementsінтерфейс, то чи можу я сказати, що я слідкую за спадщиною? Я знаю, що коли клас extendsінший клас, то це спадщина.



7
Коментар Джодрела просто неправильний. Реалізація інтерфейсу справді є спадщиною, а успадкування одного інтерфейсу від іншого - це спадкування. Звідки ми знаємо? Визначивши слово, яке ми вживаємо. Спадкування - це властивість, що спадкові члени одного типу є також членами іншого типу. За цим визначенням, просто клас, який реалізує інтерфейс, успадкував усі методи інтерфейсу; просто подивіться на клас та інтерфейс, і ви побачите, що у правильній програмі вони однакові.
Ерік Ліпперт

Я не перевірив і пішов з більшою плутаниною.
RajeeV VenkaT

18
Для чого це варто, я думаю, що ви витрачаєте багато часу на визначення слова, яке не принесе вам великої користі. Врешті-решт, всі ми знаємо, що означає реалізація інтерфейсу, і чи вважається він «спадщиною», в значній мірі не має значення для вашої щоденної роботи.
Роберт Харві

3
Я (в основному) згоден з Робертом. Я думаю, що є реальна цінність у розумінні точних технічних значень жаргонних слів, оскільки вони використовуються в різних контекстах. Але Роберт має рацію, що розуміти практичний вплив набагато корисніше! Як можна використовувати спадщину, щоб зробити свій код більш безпечним? Більш тестова? Більш багаторазові? Більш гнучка? І так далі. Знання того, що члени базових типів також є членами похідних типів, чудово, але краще все-таки знати, як ефективно його використовувати.
Ерік Ліпперт

Відповіді:


78

ОНОВЛЕННЯ: Я переглянув цю відповідь. У коментарях було підкреслено багато хороших моментів, які заслуговують на виклик.

Якщо мій клас реалізує інтерфейс, то чи можу я сказати, що я слідкую за спадщиною?

Не зовсім зрозуміло, що ви маєте на увазі під «слідування спадщиною». Давайте задамо трохи інше запитання?

Що таке спадщина?

  • Коли члени одного типу X вважаються членами іншого типу Y, ті члени Y є успадковані від X .
  • Між деякими типами існує спадковий зв’язок; тобто для деяких типів X і Y ми говоримо «Y успадковує від X».

Вони тонко різні. Це прикро, тому що це заплутано.

Які плутанини зазвичай виникають із цього тонкого розрізнення?

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

Я особисто був би щасливішим, якби специфікації Java та C # використовували слово, відмінне від "успадкованого", щоб описати взаємозв'язок між методами інтерфейсу та класами, щоб уникнути цієї плутанини. Але вони цього не роблять, і ми маємо міркувати із специфікацій, а не проти них.

Чи є у Java успадковані члени інтерфейсу за класами, які їх реалізують?

Так, деякі є. Дивіться специфікацію Java 8.4.8, яку я цитую тут для вашої зручності.

Клас C успадковує від свого прямого суперкласу та прямих суперінтерфейсів усі абстрактні та типові методи m, для яких справедливі всі наступні дії: [...]

Якщо ви говорите, що клас реалізує інтерфейс, то клас успадковує абстрактні та стандартні методи цього інтерфейсу . (Звичайно, я пропустив умови, які випливають; детальну інформацію див. У специфікації. Зокрема, клас, який реалізує член інтерфейсу, не вважається, що він успадкував цей член. Знову ж, це заплутано? Так.)

Ми зазвичай в Java заявляємо, що клас успадковує інтерфейс?

Зазвичай ми б сказали, що клас реалізує інтерфейс. Як зазначалося вище, клас може успадковувати учасників з інтерфейсу, але все ще не кажуть, що він успадковує інтерфейс. Що заплутано, так.

Чи має значення ця тонка відмінність у щоденній роботі?

Зазвичай ні. Цей вид вузького розбору специфікації є більш корисним для авторів-компіляторів, ніж розробників бізнесу. Його важливіше зрозуміти, коли використовувати інтерфейс, ніж це отримати точне визначення поняття «успадковується від».


4
Я не можу посперечатися з канонічною посиланням. Коли специфікації відрізняються, як це обов'язково роблять, прості терміни семантично перевантажуються і неоднозначно виходять із контексту. Питання позначено тегом, javaтому це правильна відповідь, якщо тільки ОП не означало іншого java:-)
Джодрелл

5
Хоча питання позначене Java, я вважаю проблематичним цитувати специфікацію мови для загального терміна. Багато мов мають інтерфейси, і їхні мовні характеристики можуть використовувати інший термін, тому використання специфічного для Java терміна може бути заплутаним при спілкуванні з розробниками, які використовують X-Lang.
Томас Оуенс

5
@ThomasOwens: Я згоден, що цей сценарій є загальним, і я повністю не згоден з вашим висновком. Рішення проблеми зв'язку ви описуєте є навчити всіх учасників , як до точних значень слів у відповідному контексті . Існують технічні умови для забезпечення цієї чіткості; використовуйте їх!
Ерік Ліпперт

5
Чому специфікація мови Java отримала остаточне слово тут? Специфікація мови часто стверджує, що "загальний розробник" не погоджується з термінологією.
Бенджамін Груенбаум

5
@BenjaminGruenbaum: Хіба я цього не знаю. Ці розробники помиляються, і вони часто беруть на себе «навчати» інших щодо своїх помилкових переконань. Ви б не повірили, що кількість мов програм програмування, які мені довелося виправити, оскільки автори мали певні абсолютно шалені переконання щодо VB, C #, JavaScript тощо, які ні в якому разі не були правильними. (Джон Скіт не був серед них; C # В глибині було правильним з самого початку! Ніколи я не робив так мало коментарів до книги і все одно отримував оплату.)
Ерік Ліпперт

26

Спадкування означає написання нового підкласу для суперкласу. Написання нового класу проти інтерфейсу реалізує цей інтерфейс. (І написання нового інтерфейсу на основі старого розширює цей інтерфейс.)

Єдиний правильний термін, який стосується всіх трьох можливостей, - це підтипування . Не кожен підтип - це підклас.


1
Книга GoF, здається, вважає успадкування інтерфейсу відповідним терміном для опису підтипу (розділ 1.6 Клас проти успадкування інтерфейсу)
gnat

"Я одного разу відвідував зустріч групи користувачів Java, де виступав спікер Джеймс Гослінг (винахідник Java). Під час пам'ятного засідання з питань запитань хтось запитав його:" Якщо ви могли б знову зробити Java, що б ви змінили? " виходьте з класів, - відповів він. Він пояснив, що справжньою проблемою були не класи як такі, а скоріше наслідування реалізації (розширення відносин). Спадкове успадкування (відносини реалізації) є кращим. Вам слід уникати успадкування реалізації, коли це можливо. " javaworld.com/article/2073649/core-java/…
ricardoramos

1

З підкласами , ти

  • успадковує стан надкласу (усі змінні екземпляри, ви їх бачите чи ні)
  • успадковувати реальні реалізації (всі неабразивні методи)

За допомогою інтерфейсів ви повністю заповнюєте контракт, застосовуючи заявлені методи.

Ось класичний спосіб на це подивитися. Тепер із Java 8 інтерфейси стають сумішшю:

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

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

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