Чи є різниця між інтерфейсами та абстрактними класами, які мають лише абстрактні методи?


9

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

Що я хочу дізнатися, чи є якісь філософські, об’єктивні та різниці в мові програмування між абстрактним класом лише з абстрактними членами та відповідним інтерфейсом?


яка мова?
кевін клайн

наскільки я можу сказати, на ваше запитання відповідають двічі у двох примірниках : тут і тут . І ці дві відповіді є агностиками мови, нічого конкретного для C # там
gnat

3
@blank Я не погодився зі статусом дубліката, застосованим до вашого питання, тому я його знову відкрив. Далі я відредагував ваше запитання, щоб далі уточнити те, що я вважаю, що ви запитуєте.
maple_shaft

Відповіді:


22

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

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

Інтерфейс - це саме те, що звучить, це інтерфейс, за допомогою якого інші класи можуть спілкуватися з об’єктом. Якщо ви хочете зробити Cat Walk, ви все в порядку, тому Cat реалізує інтерфейс CanWalk. Те саме для Ящірки, хоча вони ходять дуже інакше. Змія, з іншого боку, не реалізує CanWalk, тому ви не можете сказати це Walk. Тим часом ящірки та змія (або, можливо, більш чіткі підкласи - я не експерт), можуть як пролити шкіру, так і реалізувати CanShed, тоді як Кіт цього не зміг зробити.

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

Ось чому всі методи в інтерфейсі повинні бути реалізовані як загальнодоступні (або явно, в C #). Тому що сенс в інтерфейсі, прихованому від класу, що взаємодіє з об'єктом? Це також, чому ви можете мати кілька інтерфейсів для об'єкта, навіть коли мова не підтримує множинне успадкування.

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


4
+1, хоча коти проливають набагато більш прикро, ніж змії чи ящірки.
Меттью Флін

Технічно: абстрактні методи можна зробити захищеними. Методи інтерфейсу нахиляють.
Жак Коортс

19

У більшості мов OOP клас-реалізатор може виходити лише з одного абстрактного класу, але реалізовувати декілька інтерфейсів.


3
найбільше? які ви рахуєте? Більшість мов OOP, які я знаю, не мають інтерфейсів або абстрактних класів. C ++ має лише абстрактні класи.
кевін клайн

10
@kevincline: ймовірно, C #, Java та VB.NET.
tdammers

1
@kevincline, я думаю, що не вистачає лише "того, що має". IIRC, в Ada мотивація інтерфейсу полягала в тому, що один, дизайнери не хотіли загальної функції множинного успадкування, але особливий випадок інтерфейсу вважався занадто важливим, щоб його не було надано.
AProgrammer

@tdammers: LOL Це був жарт, правда?
кевін клайн

3

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

У таких мовах, як PHP та C #, інтерфейси забезпечують спосіб досягнення подібного поліморфізму, хоча мені не подобається називати це "спадщиною", оскільки існує концептуальна різниця між успадкуванням абстрактного класу та реалізацією інтерфейсу. Інтерфейси усувають проблему конфлікту, оскільки вони самі не забезпечують реалізації.

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

Основна концептуальна відмінність полягає в тому, що коли клас успадковує інший клас (абстрактний чи ні), існує співвідношення "є", тож a Carє a Vehicleі Dogan Animal. З інтерфейсом має значення саме те, що робить об'єкт. Тож Carі Dogвміє, Move()і споживач знає це, бо вони реалізують Movable, але Автомобіль, безумовно, не Dogє Animal. І реалізація руху буде іншою (колеса проти ніг), але споживчий код не має і не повинен хвилювати. Інтерфейси - це скоріше про споживчий код, а не про реалізацію.

Головне, якщо у вас є інтерфейси для вашої мови вибору, використовуйте їх для речей, для яких вони є. Якщо ні (як у C ++), ви можете підробити їх, використовуючи чисті абстрактні класи.


Інтерфейс також тип, так що ви можете мати IAnimal, який є і тим, Dogі Cat є .
Емі Бланкенсіп

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

2

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

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


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

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

Просто записка. У деяких мовах приватні віртуальні методи можуть бути замінені у похідних класах.
Йохан Буле

2

Так, вони різні. Інакше мовні дизайнери не забезпечили б обох. Я знаю дві мови, які розділяють класи та інтерфейси: Java та C #, мутантний клон Java. Дизайнери створили інтерфейси, щоб уникнути підтримки успадкування декількох класів. Більшість інших мов підтримують успадкування декількох класів і, отже, не розділяють класи та інтерфейси.


2

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

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

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


1
Чи не визначені абстрактні методи без будь-якої реалізації, і залишити реалізацію в спадкових класах?
Іван Пінтар

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

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

@AmyBlankenship так, більшість часу абстрактні класи мають "реальний" код (саме для цього вони і є). Але я мав на увазі абстрактні методи, в контексті суто абстрактного класу, який служить інтерфейсом на мові на зразок C ++, яка не має інтерфейсів.
Іван Пінтар
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.