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


1753

У чому саме різниця між інтерфейсом та абстрактним класом?


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

5
Це питання може також допомогти зрозуміти концепцію інтерфейсів stackoverflow.com/q/8531292/1055241
gprathour

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

2
назад у день у c ++ інтерфейс - це чистий абстрактний базовий клас із усіма реалізаціями методу = 0. Якщо одного методу не було = 0, то він має реалізацію, і абстрактна база вже не є чистою, і вже не інтерфейсом . Я думаю, що VMT має менше опосередкованості, коли багатократне успадкування використовує лише чисті абстрактні основи, але я не пам'ятаю, як вони вже виглядають, були занадто довгими.
Джим

Відповіді:


2255

Інтерфейси

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

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

Наприклад (псевдокод):

// I say all motor vehicles should look like this:
interface MotorVehicle
{
    void run();

    int getFuel();
}

// My team mate complies and writes vehicle looking that way
class Car implements MotorVehicle
{

    int fuel;

    void run()
    {
        print("Wrroooooooom");
    }


    int getFuel()
    {
        return this.fuel;
    }
}

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


Абстрактні заняття

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

Абстрактні класи схожі на інтерфейси, але вони мають щось більше: Ви можете визначити поведінку для них. Йдеться більше про те, щоб людина сказала: " Ці заняття повинні виглядати так, і вони мають спільне, тому заповніть пробіли! "

Наприклад:

// I say all motor vehicles should look like this:
abstract class MotorVehicle
{

    int fuel;

    // They ALL have fuel, so lets implement this for everybody.
    int getFuel()
    {
         return this.fuel;
    }

    // That can be very different, force them to provide their
    // own implementation.
    abstract void run();
}

// My teammate complies and writes vehicle looking that way
class Car extends MotorVehicle
{
    void run()
    {
        print("Wrroooooooom");
    }
}

Впровадження

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

У Java це правило сильно виконується, тоді як у PHP інтерфейси є абстрактними класами, де метод не оголошений.

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

Як зазвичай у програмуванні, є теорія, практика та практика іншою мовою :-)


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

187
Я не думаю, що споживання процесора - це найголовніша точка інтерфейсів.
Ден Лугг

5
@ e-satis Ви можете, будь ласка, пояснити свою точку щодо використання процесора? Чому абстрактний клас, будучи класом, збільшує використання процесора? Про який пошук ви тут звертаєтесь?
Geek

36
@ e-satis За допомогою Java 8 ви можете визначити методи за замовчуванням в інтерфейсах, що є еквівалентом того, що у абстрактних класах є не абстрактні методи. З цим доповненням я більше не бачу реальної різниці між абстрактними класами та інтерфейсом, крім того, що я повинен використовувати інтерфейси, оскільки класи можуть реалізовувати декілька інтерфейсів, але можуть успадковувати лише один клас
Ogen

23
Я думаю, що порівняння між interfaceі classз Head First Java- яскраво, щоA class defines who you are, and an interface tells what roles you could play
LittleLittleQ

872

Ключові технічні відмінності між абстрактним класом та інтерфейсом :

  • Абстрактні класи можуть мати константи, члени, заглушки методів (методи без тіла) та визначені методи , тоді як інтерфейси можуть мати лише константи та заглушки методів .

  • Методи та члени абстрактного класу можна визначити з будь-якою видимістю , тоді як всі методи інтерфейсу повинні бути визначені як public(вони визначені загальнодоступними).

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

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

  • Дочірній клас може розширювати лише один клас (абстрактний або конкретний), тоді як інтерфейс може розширюватись або клас може реалізовувати безліч інших інтерфейсів .

  • Дочірній клас може визначати абстрактні методи з однаковою або менш обмежувальною видимістю , тоді як клас, що реалізує інтерфейс, повинен визначати методи з точно такою ж видимістю (public).


123
Я думаю, що це найкраща відповідь, оскільки він висвітлює всі ключові відмінності. приклад насправді не потрібен.
Джошуа К

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

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

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

5
"При успадкуванні абстрактного класу дочірній клас повинен визначати абстрактні методи, тоді як інтерфейс може розширювати інший інтерфейс, і методи не повинні визначатися." - Це не правда. Так само, як інтерфейс може розширювати інтерфейс, не визначаючи методів, абстрактний клас може успадкувати абстрактний клас без визначення методів.
Нік

141

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

введіть тут опис зображення Взято від:

http://www.dotnetbull.com/2011/11/difference-between-abrief-class-and.html

http://www.dotnetbull.com/2011/11/what-is-ab Abstract- class- in-c- net.html http://www.dotnetbull.com/2011/11/what-is-interface-in -c-net.html


17
Вам потрібно сказати, до якої мови це стосується ("Абстрактний клас не підтримує багаторазове успадкування" - це далеко не загальновизнаний характер)
Бен Войгт

Останнє порівняння заплутане за таблицею! Методи в інтерфейсі не можуть бути статичними, але змінні є статичними остаточними Реалізовані методи в абстрактному класі можуть бути статичними
realPK

8
Член інтерфейсу повинен бути статичним остаточним. Останнє твердження неправильне.
Jawad Zeb

Я думаю, що "функціональність" у цій відповіді означає "реалізація". Не впевнені, що означає "поведінка" - можливо "підписи"?
LarsH

2
Яка мова цільового програмування тут? C #?
Пітер Мортенсен

80

Пояснення можна знайти тут: http://www.developer.com/lang/php/article.php/3604111/PHP-5-OOP-Interfaces-Ab Abstract-Classes-and-the-Adapter- Pattern.htm

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

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

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


4
Це найбільш правильна відповідь, оскільки інтерфейси PHP відрізняються від інших мов тим, що інтерфейси PHP є абстрактними класами під кришкою, тоді як інтерфейси інших мов - це підписи, яким класи повинні відповідати. Вони поводяться так само, поки немає помилок.
Tor Valamo

1
Правда, для PHP - це справді найкращий показник. Але важче дістатись із текстового блобу, ніж із простого фрагмента.
e-satis

З наданих вами визначень вони виглядають однаково, за винятком однієї деталі: інтерфейс 100% абстрактний, а абстрактний клас частково абстрактний і може мати деякі реалізації методів (можливо, всі методи можуть мати реалізацію?).
jww

41

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

Простіше кажучи, я хотів би сказати:

інтерфейс: для реалізації договору декількома непов'язаними об'єктами

абстрактний клас: реалізувати однакову або різну поведінку серед декількох пов'язаних об'єктів

З документації Oracle

Подумайте про використання абстрактних класів, якщо:

  1. Ви хочете поділитися кодом між кількома тісно пов'язаними класами.
  2. Ви очікуєте, що класи, які розширюють ваш абстрактний клас, мають багато загальних методів або полів або потребують модифікаторів доступу, крім загальнодоступних (таких як захищені та приватні).
  3. Ви хочете оголосити нестатичні або незакінчені поля.

Подумайте про використання інтерфейсів, якщо:

  1. Ви очікуєте, що незв'язані класи реалізують ваш інтерфейс. Наприклад, багато незв'язаних об'єктів можуть реалізувати Serializableінтерфейс.
  2. Ви хочете вказати поведінку певного типу даних, але не переймаючись тим, хто реалізує свою поведінку.
  3. Ви хочете скористатися множинним успадкуванням типу.

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

Якщо ви шукаєте Javaяк мову програмування, ось ще кілька оновлень:

Java 8 дещо зменшила розрив між класами interfaceта abstractкласами, надаючи функцію defaultметоду. Інтерфейс не має реалізації для методу, він більше не діє.

Докладнішу інформацію див. На цій сторінці документації .

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

Як я повинен пояснити різницю між класом інтерфейсу та абстрактним?


38

Деякі важливі відмінності:

У формі таблиці:

Різниця

Як заявив Джо з javapapers :

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

2. Змінні, оголошені в інтерфейсі Java, за замовчуванням остаточні. Абстрактний клас може містити не остаточні змінні.

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

4.Java-інтерфейс повинен бути реалізований за допомогою ключового слова "інструменти"; Абстрактний клас Java слід розширити за допомогою ключового слова "extends".

5.Інтерфейс може розширювати лише інший інтерфейс Java, абстрактний клас може розширювати інший клас Java та реалізовувати декілька Java-інтерфейсів.

6. Клас Java може реалізовувати декілька інтерфейсів, але він може розширювати лише один абстрактний клас.

7.Інтерфейс абсолютно абстрактний і його неможливо уявити; Абстрактний клас Java також не може бути ініційованим, але його можна викликати, якщо існує main ().

8.У порівнянні з абстрактними класами java інтерфейси java повільні, оскільки це вимагає додаткового опосередкування.


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

Будь ласка, згадайте і про C ++. Хоча в C ++ як такому немає ключового слова "інтерфейс", але його також часто запитують Qn regd C ++.
cbinder

@cbinder: у c ++ немає ключового слова "інтерфейс". Для різниці в c ++, будь ласка, зверніться до 1. tutorialspoint.com/cplusplus/cpp_interfaces.htm 2. tutorialspoint.com/cplusplus/cpp_interfaces.htm
softmage99

@MageshBabu Можливо, визначення функції класу, що містить чисту віртуальну функцію, робить його абстрактним класом, а не інтерфейсом
cbinder

2
У Java 8 відмінностей зараз менше. Ознайомтесь із оновленими відмінностями тут: journaldev.com/1607/…
Pankaj

31

Основний момент полягає в тому, що:

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

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

1
Інші відповіді занадто технічні. Це наближення до того, що я вважаю, є «правильною» відповіддю. Вся суть OOP полягає в семантиці, і те, незалежно від того, незалежні приватні вкладені класи отримують публічні користувачі через дорогі пошукові процесори, тут майже не має значення
Sentinel

26

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

Якщо ви хочете поліморфну ​​поведінку для класів, які абсолютно не пов'язані, використовуйте інтерфейс.


24

Я будую будівлю на 300 поверхів

План будівлі інтерфейс

  • Наприклад, сервлет (I)

Будівля споруджена до 200 поверхів - частково завершена --- реферат

  • Часткова реалізація, наприклад, загального сервера та HTTP

Будівництво будівлі завершено - бетон

  • Повна реалізація, наприклад, власного сервлета

Інтерфейс

  • Ми нічого не знаємо про реалізацію, лише вимоги. Ми можемо перейти на інтерфейс.
  • Кожен метод є загальнодоступним та абстрактним за замовчуванням
  • Це 100% чистий абстрактний клас
  • Якщо ми оголошуємо загальнодоступними, ми не можемо оголосити приватними та захищеними
  • Якщо ми оголосимо абстрактний, ми не можемо оголосити остаточний, статичний, синхронізований, строгий та власний
  • Кожен інтерфейс має публічний, статичний та остаточний
  • Серіалізація та перехідність не застосовуються, оскільки ми не можемо створити примірник для інтерфейсу
  • Енергонезалежний, оскільки він остаточний
  • Кожна змінна є статичною
  • Коли ми оголошуємо змінну всередині інтерфейсу, нам потрібно ініціалізувати змінні під час декларування
  • Екземпляр і статичний блок не дозволені

Анотація

  • Часткове виконання
  • Він має абстрактний метод. Крім того, тут використовується бетон
  • Без обмежень для модифікаторів методів абстрактних класів
  • Без обмежень для модифікаторів змінних абстрактних класів
  • Ми не можемо оголосити інші модифікатори, крім абстрактних
  • Немає обмежень для ініціалізації змінних

Взято з веб-сайту DurgaJobs


Абстрактний клас може мати конструктор
vimal krishna

4
Я повністю не згоден з цим поглядом. План - це зовсім інша концепція "інтерфейс". План конкретного варіанту є більш аналогічним статичній моделі або специфікації конструкції. Це ближче до "класу", оскільки креслення можна кілька разів інстанціювати через його конструктор, але навіть це недостатньо близько, оскільки "клас" також містить специфікацію, як конструювати (ctor), і засоби робити тому. Інтерфейс як концепція призначений для відображення певної поведінки, наприклад, нагрівання / охолодження, яка може бути застосована до різних речей, наприклад: будівель, духовок тощо.
Sentinel

18

Давайте ще раз попрацюємо над цим питанням:

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

Я зазначу основні відмінності, а решта вже пояснено:

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

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


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

"математика метафора марна", чому ти так вважаєш?
Dhananjay

12

Насправді це досить просто.

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

Отже, інтерфейс може лише "заявляти", а не визначати поведінку, яку ви хочете мати у класі.

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

А звичайний клас дозволяє лише визначити, а не оголосити поведінку / дії, якими ви хочете мати клас.

Останнє,

У Java ви можете реалізувати кілька інтерфейсів, але ви можете розширити лише один (абстрактний клас або клас) ...

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

Інтерфейси з іншого боку, ви можете просто зробити: інтерфейс C реалізує A, B

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

Сподіваємось, це має сенс.


11

Порівняння інтерфейсу та абстрактного класу невірно. Замість цього слід здійснити два порівняння: 1) інтерфейс проти класу та 2) абстрактний та заключний клас .

Інтерфейс проти класу

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

interface Package {
  String address();
}

Клас - це група об’єктів, які підкоряються договору. Наприклад, я ящик з групи "Коробка" і я підкоряюсь контракту, який вимагає Листоноша. При цьому я підкоряюся іншим договорам:

class Box implements Package, Property {
  @Override
  String address() {
    return "5th Street, New York, NY";
  }
  @Override
  Human owner() {
    // this method is part of another contract
  }
}

Анотація проти фіналу

Абстрактний клас - це група неповних предметів. Їх не можна використовувати, оскільки вони пропускають деякі частини. Наприклад, я абстрактне GPS-поле - я знаю, як перевірити свою позицію на карті:

abstract class GpsBox implements Package {
  @Override
  public abstract String address();
  protected Coordinates whereAmI() {
    // connect to GPS and return my current position
  }
}

Цей клас, якщо він успадкований / розширений іншим класом, може бути дуже корисним. Але сам по собі - він марний, оскільки не може мати об’єктів. Абстрактні заняття можуть бути будівельними елементами підсумкових занять.

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

final class DirectBox implements Package {
  private final String to;
  public DirectBox(String addr) {
    this.to = addr;
  }
  @Override
  public String address() {
    return this.to;
  }
}

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

Знову ж таки, порівнювати інтерфейси з абстрактними класами - не правильно.


9

Коротше кажучи, відмінності такі:

Синтаксичні відмінності між інтерфейсом та абстрактним класом :

  1. Методи та члени абстрактного класу можуть мати будь-яку видимість. Усі методи інтерфейсу повинні бути загальнодоступними . // Більше не відповідає дійсності від Java 9
  2. Конкретний дочірній клас абстрактного класу повинен визначати всі абстрактні методи. Абстрактний клас дитина може мати абстрактні методи. Інтерфейс розширює іншу потребу інтерфейсу не забезпечує реалізацію по замовчуванням для методів , успадкованих від батьківського інтерфейсу.
  3. Дочірній клас може розширювати лише один клас. інтерфейс може розширювати кілька інтерфейсів. Клас може реалізувати кілька інтерфейсів.
  4. Дочірній клас може визначати абстрактні методи з однаковою або менш обмежувальною видимістю, тоді як клас, що реалізує інтерфейс, повинен визначати всі методи інтерфейсу як загальнодоступні.
  5. Анотаційні класи можуть мати конструктори, але не інтерфейси .
  6. Інтерфейси Java 9 мають приватні статичні методи.

В інтерфейсах зараз:

public static- підтримується
public abstract- підтримується
public default- підтримується
private static- підтримується
private abstract- помилка
private defaultкомпіляції
private- помилка компіляції - підтримується


8

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

Визначення інтерфейсу з часом змінювалося. Як ви вважаєте, в інтерфейсі є лише декларації методів і це лише контракти? Що про статичні кінцеві змінні та що про визначення за замовчуванням після Java 8?

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

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

Див. Чому Java допускає статичні кінцеві змінні в інтерфейсах, коли вони призначені лише для контрактів? .


1
Хоча це важлива різниця, але це не єдина різниця.
Говінд Пармар

7

Інтерфейс: Поворот (поверніть вліво, поверніть праворуч)

Анотація класу: Колесо.

Клас: Рульове колесо, походить від Wheel, виставляє інтерфейсний поворот

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


6

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

Наступні приклади демонструють це.

Абстрактний клас на Java:

abstract class animals
{
    // They all love to eat. So let's implement them for everybody
    void eat()
    {
        System.out.println("Eating...");
    }
    // The make different sounds. They will provide their own implementation.
    abstract void sound();
}

class dog extends animals
{
    void sound()
    {
        System.out.println("Woof Woof");
    }
}

class cat extends animals
{
    void sound()
    {
        System.out.println("Meoww");
    }
}

Далі йде реалізація інтерфейсу на Java:

interface Shape
{
    void display();
    double area();
}

class Rectangle implements Shape 
{
    int length, width;
    Rectangle(int length, int width)
    {
        this.length = length;
        this.width = width;
    }
    @Override
    public void display() 
    {
        System.out.println("****\n* *\n* *\n****"); 
    }
    @Override
    public double area() 
    {
        return (double)(length*width);
    }
} 

class Circle implements Shape 
{
    double pi = 3.14;
    int radius;
    Circle(int radius)
    {
        this.radius = radius;
    }
    @Override
    public void display() 
    {
        System.out.println("O"); // :P
    }
    @Override
    public double area() 
    { 
        return (double)((pi*radius*radius)/2);
    }
}

Деякі важливі ключові моменти у двох словах:

  1. Змінні, задекларовані в інтерфейсі Java, за замовчуванням є остаточними. Абстрактні класи можуть мати не остаточні змінні.

  2. Змінні, задекларовані в інтерфейсі Java, за замовчуванням статичні. Абстрактні класи можуть мати нестатичні змінні.

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


4

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

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

Підсумок

  1. Інтерфейс визначає контракт, який вам виконає деяка реалізація .

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

Альтернативний підсумок

  1. Інтерфейс призначений для визначення загальнодоступних API
  2. Абстрактний клас призначений як для внутрішнього використання, так і для визначення SPI

Про важливість приховування деталей реалізації

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

З іншого боку, користувачам високого рівня списку не дуже важливо, як він реально реалізований, і їх слід ізолювати від цих деталей. Уявімо, що Java не відкрила Listінтерфейс, а лише конкретний Listклас, який є насправді тим, що LinkedListзараз є. Усі розробники Java розробили б свій код, щоб він відповідав деталям реалізації: уникайте випадкового доступу, додайте кеш для прискорення доступу або просто повторного вдосконалення ArrayListсамостійно, хоча це було б несумісне з усім іншим кодом, який насправді працює зList лише. Це було б жахливо ... Але тепер уявіть, що майстри Java насправді усвідомлюють, що пов'язаний список жахливий для більшості фактичних випадків використання, і вирішили переключитися на список масивів лише для своїхListклас доступний. Це вплине на ефективність будь-якої програми Java у світі, і люди не будуть раді цього. І головний винуватець у тому, що дані про впровадження були доступні, і розробники припускали, що ці деталі є постійним контрактом, на який вони можуть розраховувати. Ось чому важливо приховати деталі реалізації та визначити лише абстрактний контракт. Це мета інтерфейсу: визначити, який тип введення приймає метод, і який вихід очікується, не оголюючи всіх кишок, які спокушали б програмістів налаштувати свій код, щоб відповідати внутрішнім деталям, які можуть змінитися з будь-яким майбутнім оновленням .

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

API та SPI

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

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

Різниця між API та SPI є тонкою, але важливою: для API фокус робиться на тому, хто його використовує , а для SPI - фокус на тому, хто його реалізує .

Додавання методів до API просто, усі існуючі користувачі API все одно будуть компілювати. Додавання методів до SPI важко, оскільки кожному постачальнику послуг (конкретна реалізація) доведеться впроваджувати нові методи. Якщо інтерфейси використовуються для визначення SPI, постачальнику доведеться випускати нову версію кожного разу, коли контракт SPI буде змінено. Якщо замість цього використовуються абстрактні класи, нові методи можна або визначити через існуючі абстрактні методи, або як порожні throw not implemented exceptionзаглушки, що дозволить принаймні зіставити та запустити старішу версію реалізації служби.

Примітка про методи Java 8 та методи за замовчуванням

Хоча Java 8 представила методи за замовчуванням для інтерфейсів, що робить лінію між інтерфейсами та абстрактними класами ще більш розмитою, але це було не так, що реалізація може повторно використовувати код, а щоб спростити зміну інтерфейсів, які служать і API, і як SPI (або неправильно використовуються для визначення SPI замість абстрактних класів).

Який використовувати?

  1. Чи повинна ця річ публічно використовуватися іншими частинами коду чи іншим зовнішнім кодом? Додайте до нього інтерфейс, щоб приховати деталі реалізації від публічного абстрактного договору, що є загальною поведінкою речі.
  2. Чи є , що то , що передбачається мати кілька реалізацій з великою кількістю коди в загальному? Зробіть як інтерфейс, так і абстрактну, неповну реалізацію.
  3. Чи коли-небудь буде лише одна реалізація, і ніхто більше не використовуватиме її? Просто зробіть це конкретним класом.
    1. "ever" - це тривалий час, ви можете захистити його і все ж додати інтерфейс поверх нього.

Висновок: навпаки часто неправильно робиться: коли ви використовуєте річ , завжди намагайтеся використовувати найзагальніший клас / інтерфейс, який вам насправді потрібен. Іншими словами, не оголошуйте свої змінні як ArrayList theList = new ArrayList(), якщо тільки ви насправді не маєте дуже сильної залежності від того, що це список масиву , і жоден інший тип списку не скоротить його для вас. Використовуйте List theList = new ArrayListнатомість або навіть Collection theCollection = new ArrayListякщо факт, що це список, а не будь-який інший тип колекції, насправді не має значення.


4

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

Я обмежував знання OOP, але бачити інтерфейси як еквівалент прикметника в граматиці працював для мене до цих пір (виправте мене, якщо цей метод хибний!). Наприклад, імена інтерфейсу - це як атрибути чи можливості, які ви можете надати класу, а клас може мати багато з них: ISerializable, ICountable, IList, ICacheable, IHappy, ...


3

Спадщина використовується для двох цілей:

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

  • Щоб дозволити використовувати посилання на об'єкти одного типу за допомогою коду, який очікує посилання на об’єкт супертипу.

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

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

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


3

Ключові моменти:

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

Перевага:

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

знайти детальну інформацію тут ... http://pradeepatkari.wordpress.com/2014/11/20/interface-and-ab абстракт-class-in-c-oops/


3

Найкоротший спосіб підбити його - interfaceце:

  1. Повністю абстрактний, крім defaultі staticметодів; хоча він має визначення (підписи методів + реалізації) для defaultта staticметодів, він має лише декларації (підписи методів) для інших методів.
  2. Залежить від більш легких правил, ніж класи (клас може реалізовувати декілька interfaces, а a interfaceможе наслідувати від декількох interfaces). Всі змінні неявно постійні, незалежно від того, вказані вони public static finalчи ні. Усі члени неявно public, незалежно від того, вказані вони такими чи ні.
  3. Зазвичай використовується як гарантія того, що клас реалізації буде мати зазначені функції та / або бути сумісним з будь-яким іншим класом, який реалізує той самий інтерфейс.

Тим часом abstractклас:

  1. Куди завгодно, від повністю абстрактних до повністю впроваджених, із тенденцією до використання одного або кількох abstractметодів. Може містити як декларації, так і визначення, декларації позначені якabstract .
  2. Повноцінний клас з дотриманням правил, які керують іншими класами (може успадковувати лише один клас), за умови, що він не може бути ініційований (оскільки немає гарантії його повного впровадження). Може мати змінні незмінних членів. Можна здійснювати контроль доступу членів, обмежуючи користувач , як protected, privateабо приватний пакет (не вказано).
  3. Зазвичай використовується або для надання такої кількості реалізації, на яку може ділитися декілька підкласів, або для забезпечення такої кількості реалізації, скільки програміст здатний забезпечити.

Або, якщо ми хочемо , щоб закип'ятити все це вниз до однієї фрази: interfaceце те , що клас реалізації має , але abstractклас є те , що підклас є .


3

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


3

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

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


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

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

3

Відмінності між абстрактним класом та інтерфейсом від імені реальної реалізації.

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

Деякі інші випадки використання, коли нам слід використовувати інтерфейс.

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

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

Приклад абстрактного класу:

 public abstract class DesireCar
  {

 //It is an abstract method that defines the prototype.
     public abstract void Color();

  // It is a default implementation of a Wheel method as all the desire cars have the same no. of wheels.   
 // and hence no need to define this in all the sub classes in this way it saves the code duplicasy     

  public void Wheel() {          

               Console.WriteLine("Car has four wheel");
                }
           }


    **Here is the sub classes:**

     public class DesireCar1 : DesireCar
        {
            public override void Color()
            {
                Console.WriteLine("This is a red color Desire car");
            }
        }

        public class DesireCar2 : DesireCar
        {
            public override void Color()
            {
                Console.WriteLine("This is a red white Desire car");
            }
        }

Приклад інтерфейсу:

  public interface IShape
        {
          // Defines the prototype(template) 
            void Draw();
        }


  // All the sub classes follow the same template but implementation can be different.

    public class Circle : IShape
    {
        public void Draw()
        {
            Console.WriteLine("This is a Circle");
        }
    }

    public class Rectangle : IShape
    {
        public void Draw()
        {
            Console.WriteLine("This is a Rectangle");
        }
    }

3

Ви можете знайти чітку різницю між інтерфейсом та абстрактним класом.

Інтерфейс

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

Анотація класу

  • Абстрактний клас містить абстрактні та не абстрактні методи.

  • Не змушує користувачів реалізовувати всі методи при спадкуванні абстрактного класу.

  • Містить усі види змінних, включаючи примітивні та непримітивні

  • Заявіть за допомогою абстрактного ключового слова.

  • Методи та члени абстрактного класу можна визначити з будь-якою видимістю.

  • Дочірній клас може розширювати лише один клас (абстрактний або конкретний).


2

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

Інтерфейс - це креслення / шаблон методів (наприклад, задається будинок на папері (інтерфейсний будинок), і різні архітектори будуть використовувати свої ідеї для його побудови (класи архітекторів, що реалізують інтерфейс будинку). Це колекція абстрактні методи, методи за замовчуванням, статичні методи, кінцеві змінні та вкладені класи. Усі учасники будуть або остаточними, або загальнодоступними, захищені та приватні специфікатори доступу заборонені. Створення об'єктів не дозволено. Клас повинен бути створений, щоб використовувати реалізація інтерфейсу, а також переосмислення абстрактного методу, оголошеного в інтерфейсі. Інтерфейс - хороший приклад вільної зв'язку (динамічний поліморфізм / динамічне прив'язування) Інтерфейс реалізує поліморфізм та абстракцію. Він говорить, що робити, але як це зробити, визначається клас для виконання. Наприклад,sa автомобільна компанія, і вона хоче, щоб деякі функції були однаковими для всіх автомобілів, які вона виготовляє, для того, щоб компанія виготовляла інтерфейс, який буде мати такі особливості і різні класи автомобілів (як Maruti Suzkhi, Maruti 800) переможе ті особливості (функції).

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


2

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


1

В інтерфейсі всі методи повинні бути лише визначеннями, не слід реалізовувати жоден.

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


1

У нас є різні структурні / синтаксичні відмінності між інтерфейсом та абстрактним класом. Ще деякі відмінності є

[1] Різниця на основі сценарію :

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

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

[2] Концептуальна різниця :

"Чи потрібно нам надавати більше абстрактних методів у майбутньому", якщо ТАК робить його абстрактним класом і якщо НІ зробити його інтерфейсом.

(Найбільш підходить і дійсний до java 1.7)


1

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

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

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

введіть тут опис зображення

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

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