Інтерфейс проти абстрактного класу (загальний OO)


1413

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

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

Інтерфейс:

Кожен окремий метод, оголошений в інтерфейсі, повинен бути реалізований у підкласі. В інтерфейсі можуть існувати лише події, делегати, властивості (C #) та методи. Клас може реалізувати декілька інтерфейсів.

Реферат:

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

  1. Зрештою, інтерв'юер поставив питання "Що, якби у вас був клас" Анотація "лише з абстрактними методами? Чим це буде відрізнятися від інтерфейсу?" Я не знав відповіді, але думаю, що це спадщина, як згадувалося вище?

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

Дивіться також :


412
Хоча я думаю, що важливо знати різницю між ними, це не гарне питання інтерв'ю, imo. Якщо тільки робота не була написання книги на теми OO. Тобі краще не працювати на тих діт-битів.
Алан

107
@Alan: Мені це справді подобається як питання про інтерв'ю, але я не хотів би когось так обганяти - я, мабуть, розміщую це більше на кшталт "Де ви б обрали інтерфейс над абстрактним базовим класом, визначаючи ієрархію? ", чи щось подібне.
Рід Копсі

11
Можливо, вони були після більш орієнтованої на дизайн відповіді ... хоча, як і ви, я би поставився до цього як до технічного питання.
CurtainDog

16
Хороші табличні відмінності тут: mindprod.com/jgloss/interfacevsabstract.html
Rajat_R

30
@Kave: I insisted you can't have a public variable inside an interface.Я думаю, що інтерфейс може мати публічну змінну. Фактично змінні інтерфейсу автоматично є загальнодоступними та остаточними.
Учень

Відповіді:


746

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

У .NET (схоже на Java):

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

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

Дійсно, є ідіома C ++ під назвою Невіртуальний інтерфейс (NVI), де загальнодоступні методи - це невіртуальні методи, які "стикаються" з приватними віртуальними методами:


7
Дякую. Я думаю, оскільки у вашій відповіді згадується стан + хороший огляд усіх решти, я відзначаю вашу відповідь як остаточну відповідь. Ви маєте рацію, я попросив генерального ОО, оскільки мій перший інтерв'юер просив генерального ОО, але, оскільки я хлопець C #, я, як правило, це забуваю. ;-) Також дякую за пояснення C ++, як завжди c ++ - це розум.
Хьюман

6
Я думаю, що ключовим моментом у поясненні, яке надав Майкл, є те, що при впровадженні інтерфейсу ОБОВ'ЯЗКОВО реалізувати всіх членів інтерфейсу, але при успадкуванні від абстрактного класу дочірній клас НЕ ПОТРІБНИЙ для реалізації членів свого батька
Гільєрмо Гомес

82
+1: Я б хотів зробити ставку, що ті мавпи, які проводять інтерв'ю, навіть не усвідомлюють, що інші мови реалізують ОО по-іншому.
Гонки легкості на орбіті

2
@JL Я не бачу, де криється проблема. Здається, ви переплутали абстрактний метод з абстрактним класом. Абстрактні методи не мають реалізації. Однак, всередині абстрактного класу , деякі методи можуть бути абстрактними (тобто без реалізації) в той час як деякі інші можуть дійсно мати реалізацію.
xji

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

866

Як щодо аналогії: коли я був у ВВС, я пішов на пілотну підготовку і став пілотом США (ВВС США). На той момент я не мав кваліфікації літати що-небудь, і мені довелося відвідувати навчання типу літаків. Після того як я отримав кваліфікацію, я був пілотом (абстрактний клас) та пілотом С-141 (конкретний клас). В одному зі своїх завдань мені поклали додатковий обов'язок: працівник служби безпеки. Тепер я був ще пілотом та пілотом С-141, але також виконував обов'язки офіцера з безпеки (я реалізував, так би мовити, ISafetyOfficer). Пілоту не потрібно було бути працівником служби безпеки, це могли зробити і інші люди.

Усі пілоти США повинні дотримуватися певних правил ВВС, а всі пілоти С-141 (або F-16, або Т-38) "є пілотами США. Працівник служби безпеки може бути будь-хто. Отже, підсумовуючи:

  • Пілот: абстрактний клас
  • C-141 Пілот: клас бетону
  • Офіцер з питань безпеки: інтерфейс

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


87
Мені дуже подобається ця аналогія, вона використовує простий приклад, щоб пояснити дещо складну тему
Кевін Боверсокс

13
Це найкращий спосіб зрозуміти складну термінологію ОО. Коротше кажучи, вся теорія варта лише тоді, коли ви можете її практично використати. @ Джей, ти повторно проаналізуєш легко кілька пунктів кулі (в основному проникаючий розум замість того, щоб поглинутись!)
проти

54
Я ще трохи розгублений. Скажімо, тепер ви отримали кваліфікацію F-16 і T-38, тому зараз клас Jayне може успадковувати з декількох класів (пілот C-141, пілот F-16 і пілот T-38), чи означає це, чиї класи повинні стати інтерфейсами? Дякую
Олексій Окрушко

37
Багато людей справедливо дали +1 коментарю Алекса, оскільки це виявляє деяку слабкість у цьому прикладі. По-перше, я б сказав, що Джей був би екземпляром C-141Pilot, а не своїм класом. Крім того, оскільки в США 99% всіх пілотів одночасно мають кваліфікацію в одному літаку (значні винятки FCF та тестові пілоти) я не розглядав численні кваліфікації і як це можна було б реалізувати. Як я знаю пілота, який 50 років тому кваліфікувався одночасно в 25 різних літальних апаратах, я думаю, що це є прикладом того, як ми НЕ хочемо використовувати багатократне успадкування.
Джей

20
Оскільки навряд чи один пілот може літати більше ніж один літак одночасно, це буде гарною можливістю реалізувати стратегію. Пілот мав би колекцію сертифікатів і вибрав би правильну під час виконання. Сертифікати кодуються як поведінка, яка реалізує інтерфейс IFlyPlane, методами TakeOff, Land, Eject.
Майкл Блекберн

221

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

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

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

Наприклад, наприклад. Автомобіль та Вантажівка поділяють багато основних властивостей та поведінки автомобільного абстрактного класу, але вони також поділяють певні периферійні поведінки, такі як Створення вихлопних газів, які поділяють навіть не автомобільні класи, такі як Drillers або PowerGenerators і не обов'язково визначають Автомобіль чи Вантажівку , тому автомобілі, вантажівки, дирилери та PowerGenerator можуть спільно використовувати один інтерфейс IExhaust.


32
Я думаю, що ще кращою аналогією було б "useFuel", яке б показало контрактний характер інтерфейсу.
Pureferret

@Pureferret, якщо accelerateце частина основної поведінки абстрактного автомобільного класу, то я не можу сказати, що accelerateпоказує характер контракту . що таке контрактний характер? чому це слово contractвводиться, коли ми говоримо interface?
переобмін

@overexchange, оскільки, як правило, інтерфейс знаходиться саме там, де зустрічаються дві "поверхні", але слово "контракт" означає, що існує узгодження того, як зустрічаються дві "поверхні". Не має сенсу (принаймні, для мене), що генерувати вихлопи - це те, про що ти «згоден». Але має сенс (знову-таки для мене), що ви можете домовитись про необхідність використанняFuel.
Pureferret

1
@Pureferret я підняв запит за посиланням на те саме
overexchange

1
@Pureferret Якщо interfaceпотрібно мати периферійну поведінку, то чому public interface List<E> extends Collection<E> {}він призначений для опису поведінки основних list? це насправді суперечить відповіді прасуна. І те, Collection<E>і List<E>тут є інтерфейсами.
переобмін

198

Короткий: абстрактні класи використовуються для моделювання ієрархії класів подібних схожих класів (Наприклад, тварина може бути абстрактним класом, а людина, лев, тигр можуть бути конкретними похідними класами)

І

Інтерфейс використовується для зв'язку між двома схожими / не схожими класами, що не хвилює тип класу, що реалізує інтерфейс (наприклад, висота може бути властивістю інтерфейсу, і це може бути реалізовано Human, Building, Tree. Не має значення, чи можна їсти ти можеш плавати, ти можеш померти чи будь-що .. важливо лише те, що тобі потрібно мати висоту (реалізація у вашому класі)).


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

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

2
@dhananjay: я бачу, як Висота може бути відокремлена від концепції класу Animal і може бути від іншого іншого класу, але що саме ви маєте на увазі під «спілкуванням» між класами? Це просто визначення висоти для власного класу, правда?
TTT

77

Є кілька інших відмінностей -

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

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

Абстрактні базові класи можна змінювати у v2 +, не порушуючи API. Зміни в інтерфейсах порушують зміни.

[C # /. NET Specific] Інтерфейси, на відміну від абстрактних базових класів, можуть застосовуватися до типів значень (структур). Структури не можуть успадковувати абстрактні базові класи. Це дозволяє застосовувати поведінкові договори / вказівки щодо використання щодо типів цінності.


5
+1 - ключовий момент, що в класі можна реалізувати більше одного інтерфейсу.
cgp

Це єдина реальна перевага інтерфейсів над абстрактними базовими класами, IMO. В іншому випадку я погоджуюся з настановами щодо дизайну .NET, які зараз кажуть "віддайте перевагу абстрактним базовим класам над інтерфейсами"
Reed Copsey

Хоча, було б цікаво, якби ви могли додати, що це також інтерфейси можна застосувати до будь-якого класу.
cgp

1
@altCognito: Зрозуміло, що це було впорядковано з другим абзацом. Це нагадало мені, що інтерфейси працюють на типи значень, тому я додав це.
Рід Копсей

Дуже дякую за цей точний опис. Це дійсно дуже корисно. Я тут новий. Шкода, що ви не можете вибрати два відповіді як "відповідь". Що мене бентежить - це використання абстрактного базового класу. Усі абстрактні класи мають бути базовим класом підкласу. Навіщо називати додаткову основу?
Хьюман

68

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

public class Vehicle {
    private Driver driver;
    private Seat[] seatArray; //In java and most of the Object Oriented Programming(OOP) languages, square brackets are used to denote arrays(Collections).
    //You can define as many properties as you want here ...
}

Тепер велосипед ...

public class Bicycle extends Vehicle {
    //You define properties which are unique to bicycles here ...
    private Pedal pedal;
}

І автомобіль ...

public class Car extends Vehicle {
    private Engine engine;
    private Door[] doors;
}

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

Анотація заняття

Абстрактні заняття - неповні об’єкти. Щоб зрозуміти це далі, давайте ще раз розглянемо аналогію транспортного засобу.
Можна керувати транспортним засобом. Правильно? Але різні транспортні засоби рухаються по-різному ... Наприклад, ви не можете керувати автомобілем так само, як за кермом велосипеда.
Тож як представити функцію приводу транспортного засобу? Складніше перевірити, що це за транспортний засіб, і керувати ним власною функцією; вам доведеться змінювати клас драйвера знову і знову, додаючи новий тип транспортного засобу.
Тут випливає роль абстрактних класів та методів. Ви можете визначити метод приводу як абстрактний, щоб сказати, що кожен успадковуваний дитина повинен реалізувати цю функцію.
Тож якщо ви модифікуєте клас автомобіля ...

//......Code of Vehicle Class
abstract public void drive();
//.....Code continues

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

Інтерфейси Інтерфейси абсолютно неповні. Вони не мають жодних властивостей. Вони просто вказують на те, що успадковані діти здатні щось робити ...
Припустимо, у вас з собою різні типи мобільних телефонів. Кожен з них має різні способи виконання різних функцій; Наприклад: дзвоніть людині. Виробник телефону вказує, як це зробити. Тут мобільні телефони можуть набрати номер - тобто це можливість набору номера. Представимо це як інтерфейс.

public interface Dialable {
    public void dial(Number n);
}

Тут виробник Dialable визначає, як набрати номер. Вам просто потрібно дати йому номер для набору.

// Makers define how exactly dialable work inside.

Dialable PHONE1 = new Dialable() {
    public void dial(Number n) {
        //Do the phone1's own way to dial a number
    }
}

Dialable PHONE2 = new Dialable() {
    public void dial(Number n) {
        //Do the phone2's own way to dial a number
    }
}


//Suppose there is a function written by someone else, which expects a Dialable
......
public static void main(String[] args) {
    Dialable myDialable = SomeLibrary.PHONE1;
    SomeOtherLibrary.doSomethingUsingADialable(myDialable);
}
.....

Цим, використовуючи інтерфейси замість абстрактних класів, автору функції, яка використовує Діабел, не потрібно турбуватися про його властивості. Наприклад: чи є сенсорний екран або набір клавіатури, чи це стаціонарний стаціонарний телефон або мобільний телефон. Вам просто потрібно знати, чи можна це набрати; чи успадковує (або реалізує) інтерфейс Dialable.

І ще важливіше , якщо коли-небудь ви переключите Діабел на інший

......
public static void main(String[] args) {
    Dialable myDialable = SomeLibrary.PHONE2; // <-- changed from PHONE1 to PHONE2
    SomeOtherLibrary.doSomethingUsingADialable(myDialable);
}
.....

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

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

Детальніше Абстрактні класи проти інтерфейсів


Неправда, що "Інтерфейси не мають жодних властивостей".
Bigeyes

@Bigeyes, java не дозволяє властивості в інтерфейсах. Я думав, що так само і в інших мовах. Не могли б ви пояснити більше?
fz_salam

Я маю на увазі C # /. Net. Дивіться приклад
Bigeyes

@Bigeyes для C #, де інтерфейси можуть мати властивості, чи не повторно вводиться проблема множинного успадкування? Що відбувається, коли клас використовує кілька інтерфейсів, які визначили одне і те ж властивість? Просто цікаво дякую
stackPusher

@happycoder: re: "Тут, використовуючи інтерфейси замість абстрактних класів, вам не потрібно турбуватися про його властивості. Наприклад: чи має сенсорний екран або набір клавіатури, чи це стаціонарний стаціонарний телефон або мобільний телефон. Вам просто потрібно знайте, чи є вона набирається; успадковує (чи реалізує) інтерфейс Dialable. " - Ви можете показати це на прикладі коду, також не бачили, як це буде успадковано ...
TTT

45

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

Веб-сайт Oracle пропонує ключові відмінності між класом interfaceта abstractкласом.

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

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

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

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

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

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

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

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


33

Інтерв'юери галять дивне дерево. Для таких мов, як C # і Java, є різниця, але в інших мовах, як C ++, немає. Теорія ОО не відрізняє двох, а лише синтаксис мови.

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

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


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

31

Реалізуючи інтерфейси, ви досягаєте складу ("has-a" відносини) замість спадкування ("is-a" відносини). Це важливий принцип, який слід пам’ятати, коли мова йде про речі, такі як шаблони дизайну, де потрібно використовувати інтерфейси для досягнення композиції поведінки замість спадкування.


17
Інтерфейси досягають, ІМО, більшої кількості відносин "Дії як". Інкапсуляція досягає композиції краще, ніж інтерфейс.
Рід Копсі

12
Я не думаю, що реалізація інтерфейсів підходитиме до складу.
Pavan Dittakavi

Плюс до цього, інтерфейс скоріше використовувати для опису "можливостей", як-от IDisposable. Він використовувався для обміну функціональністю між класами, щоб ці класи "вміли щось робити". Більш приклад IFlyable може бути реалізований птахом і літаком. Але Bird може походити з Class Creature, де літальний апарат походить від AirCraft.
Peter.Wang

26

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

  1. Коли ми повинні використовувати інтерфейс?

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

  2. Коли нам слід використовувати абстрактний клас?

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

    Інтерфейс

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

    Анотація

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

    Інтерфейс

    Ми не можемо оголосити інтерфейс приватним, захищеним

    З. Чому ми не визнаємо Інтерфейс приватним і захищеним?

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

    Метод інтерфейсу
    також ми не можемо оголосити інтерфейс приватним, захищеним, остаточним, статичним, синхронізованим, рідним .....

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

    Анотація

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

    Інтерфейс

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

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

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

    Анотація

    Абстрактна змінна немає необхідності оголошувати публічний статичний фінал.

Сподіваюся, ця стаття корисна.


4
Я не згоден з цим пунктом: Abstract class must have at lease one abstract method.Можна мати клас Анотація без абстрактного методу, якщо ви його реалізуєте. ДОВІДКА: An abstract class is a class that is declared abstract—it may or may not include abstract methods.Джерело джерела
Devner

Ви говорите про технічні деталі та реалізацію, ви не відповідаєте на питання з точки зору загального OOP
Billal Begueradj

26

Концептуально кажучи, зберігаючи специфічну для мови реалізацію, правила, переваги та досягнення будь-якої мети програмування, використовуючи кого-небудь або обох, можна чи не можу мати код / ​​дані / властивість, бла-бла, одиночне чи декілька спадків, всі осторонь

1- Абстрактний (або чистий реферат) Клас призначений для реалізації ієрархії. Якщо ваші бізнес-об’єкти виглядають дещо структурно схожими, представляючи тип відносин батько-дитина (ієрархія), тоді використовуються класи успадкування / Анотація. Якщо у вашій бізнес-моделі немає ієрархії, успадкування не слід використовувати (тут я не кажу про логіку програмування, наприклад, деякі структури дизайну вимагають успадкування). Концептуально абстрактний клас - це метод реалізації ієрархії бізнес-моделі в OOP, він не має нічого спільного з інтерфейсами, насправді порівнювати абстрактний клас з інтерфейсом безглуздо, оскільки обидва концептуально абсолютно різні речі, в інтерв'ю його просять просто перевірити поняття, оскільки, схоже, вони забезпечують дещо однаковий функціонал, коли мова йде про реалізацію, і ми, програмісти, зазвичай більше наголошуємо на кодуванні. [Майте на увазі також, що абстракція відрізняється від абстрактного класу].

2- Інтерфейс - це договір, повна функціональність бізнесу, представлена ​​однією або кількома наборами функцій. Ось чому він реалізується і не успадковується. Бізнес-об’єкт (частина ієрархії чи ні) може мати будь-яку кількість повноцінних функціональних можливостей бізнесу. Це не має нічого спільного з абстрактними класами, означає спадщину взагалі. Наприклад, людина може RUN, слон може RUN, птах може RUN і так далі, всі ці об'єкти різної ієрархії реалізували б інтерфейс RUN або інтерфейс EAT або SPEAK. Не вступайте в реалізацію, оскільки ви могли б реалізувати її як абстрактні класи для кожного типу, що реалізують ці інтерфейси. Об'єкт будь-якої ієрархії може мати функціонал (інтерфейс), який не має нічого спільного з його ієрархією.

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

Коли вас запитують про різницю, це насправді концептуальна різниця, а не різниця в мовно-реалізованій реалізації, якщо не запитано прямо.

Я вважаю, що обидва інтерв'юери очікували прямої різниці між цими двома, і коли вам не вдалося, вони спробували привести вас до цієї різниці, застосувавши ОДНО в якості ДРУГОГО

Що робити, якщо у вас був клас "Анотація" лише з абстрактними методами?


Це в значній мірі підсумовує відповідь на це питання досить добре.
pranavn

функціональність реалізована проти структури розширена, приємно!
harshvchawla

21

Для .Net,

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

EDIT: В іншій примітці я навіть не використовував би фразу "підклас" (або фразу "успадкування") для опису класів, які "визначені для реалізації" інтерфейсу. Для мене інтерфейс - це визначення договору, якому повинен відповідати клас, якщо він був визначений для "реалізації" цього інтерфейсу. Це нічого не успадковує ... Ви повинні все додати самостійно, прямо.


2
Так! Держава! Ось що мав на увазі другий інтерв'юер своїм диваним способом сказати "загальну змінну" всередині інтерфейсу. огонь! Анотація Класи можуть мати стан, інтерфейси не можуть! І так, всі інші погоджуються і на відмінності між способами їх успадкування, які я забув згадати, але з'ясував уже пізніше. :) Дякую всім!
Хьюман

4
Більше, ніж просто стан .... Абстрактні класи можуть мати ВПРОВАДЖЕННЯ. тобто у них можуть бути методи з кодом, який насправді запускає і робить щось, що успадковується та виконується екземплярами базових класів ... Не так із інтерфейсами
Чарльз Бретана

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

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

20

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

Плюси:

  1. Дозволяє багаторазове успадкування
  2. Забезпечує абстрагування, не розкриваючи, який саме тип об'єкта використовується в контексті
  3. забезпечує узгодженість конкретним підписом договору

Мінуси:

  1. Потрібно виконати всі визначені договори
  2. Не може бути змінних або делегатів
  3. Після визначення їх неможливо змінити без порушення всіх класів

Анотаційний клас : слід використовувати там, де ви хочете мати базову поведінку або реалізацію за замовчуванням для компонентів, пов'язаних один з одним

Плюси:

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

Мінуси:

  1. Неможливо створити інстанцію
  2. Не підтримує багаторазове успадкування

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

@ denis631 абстрактний клас трохи швидший, ніж інтерфейс, оскільки пошук та виклик задіяні в методі інтерфейсу. читайте цей coderanch.com/t/503450/java/ab
абстракт-

17

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

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

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

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


13
After all that, the interviewer came up with the question "What if you had an 
Abstract class with only abstract methods? How would that be different
from an interface?" 

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

An another interviewer asked me what if you had a Public variable inside
the interface, how would that be different than in Abstract Class?

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

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


13
  1. Інтерфейс:
    • Ми не реалізуємо (або визначаємо) методи, ми робимо це у похідних класах.
    • Ми не оголошуємо змінних членів в інтерфейсах.
    • Інтерфейси виражають відношення HAS-A. Це означає, що вони є маскою предметів.
  2. Реферат:
    • Ми можемо оголосити та визначити методи в абстрактному класі.
    • Ми приховуємо його конструктори. Це означає, що немає прямо створеного з нього об’єкта.
    • Абстрактний клас може містити змінні члена.
    • Похідні класи успадковують абстрактний клас, що означає, що об'єкти з похідних класів не маскуються, вони успадковують абстрактний клас. Зв'язок у цьому випадку IS-A.

Це моя думка.


12

Скопійовано з CLR через C # Джефрі Ріхтер ...

Я часто чую запитання: "Чи слід створити базовий тип або інтерфейс?" Відповідь не завжди чіткий.

Ось кілька рекомендацій, які можуть вам допомогти:

■■ Зв'язок IS-A проти CAN-DO Тип може успадкувати лише одну реалізацію. Якщо похідний тип не може вимагати відносин IS-A з базовим типом, не використовуйте базовий тип; використовувати інтерфейс. Інтерфейси передбачають відношення CAN-DO. Якщо, можливо, функціонал CAN-DO належить до різних типів об'єктів, використовуйте інтерфейс. Наприклад, тип може конвертувати екземпляри себе в інший тип (IConvertible), тип може серіалізувати примірник себе (ISerializable) тощо. Зауважте, що типи значень повинні бути похідні від System.ValueType, а отже, їх неможливо отримати від довільного базового класу. У цьому випадку потрібно використовувати відношення CAN-DO та визначити інтерфейс.

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

■■ Послідовна реалізація Незалежно від того, наскільки добре задокументований контракт на інтерфейс, дуже малоймовірно, що кожен виконає контракт на 100 відсотків правильно. Фактично, COM страждає від цієї самої проблеми, тому деякі COM-об'єкти працюють правильно лише з Microsoft Word або з Windows Internet Explorer. Забезпечивши базовий тип з хорошою реалізацією за замовчуванням, ви починаєте використовувати тип, який працює і добре перевірений; Ви можете змінити деталі, які потребують модифікації.

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


1
@AbdullahShoaib - це і хто може, але не може, тут є різниця. це основна причина, нам потрібен інтерфейс. Частина поведінки також буде частиною abstract class.
переобмін

10

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

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

C # дозволяє також успадкувати інтерфейс, пам’ятайте.


1
Використовуючи терміни горизонтальну та вертикальну, було дуже зрозуміло уявити різницю.
Нескінченність

10

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

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

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

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

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


10

Як ви, можливо, отримали теоретичні знання від експертів, я не витрачаю багато слів на повторення всіх цих тут, скоріше дозвольте мені пояснити простим прикладом, де ми можемо використовувати / не можемо використовувати Interfaceі Abstract class.

Розглянемо, що ви розробляєте додаток, щоб перелічити всі функції автомобілів. У різних точках вам потрібна спільна спадщина, оскільки деякі властивості, такі як DigitalFuelMeter, Кондиціонер, регулювання сидіння тощо, є загальними для всіх автомобілів. Так само нам потрібно успадкувати лише для деяких класів, оскільки деякі властивості, як гальмівна система (ABS, EBD), застосовні лише для деяких автомобілів.

Нижній клас виступає базовим класом для всіх автомобілів:

public class Cars
{
    public string DigitalFuelMeter()
    {
        return "I have DigitalFuelMeter";
    }

    public string AirCondition()
    {
        return "I have AC";
    }

    public string SeatAdjust()
    {
        return "I can Adjust seat";
    }
}

Поміркуйте, у нас є окремий клас для кожної машини.

public class Alto : Cars
{
    // Have all the features of Car class    
}

public class Verna : Cars
{
    // Have all the features of Car class + Car need to inherit ABS as the Braking technology feature which is not in Cars        
}

public class Cruze : Cars
{
    // Have all the features of Car class + Car need to inherit EBD as the Braking technology feature which is not in Cars        
}

Розглянемо, що нам потрібен метод успадкування технології гальмування автомобілів Verna та Cruze (не застосовується для Alto). Хоча обидва використовують гальмівну технологію, "технологія" відрізняється. Таким чином, ми створюємо абстрактний клас, в якому метод буде оголошено абстрактним і його слід реалізувати у своїх дочірніх класах.

public abstract class Brake
{
    public abstract string GetBrakeTechnology();
}

Зараз ми намагаємось успадкувати цей абстрактний клас, і тип гальмівної системи реалізований у Verna та Cruze:

public class Verna : Cars,Brake
{
    public override string GetBrakeTechnology()
    {
        return "I use ABS system for braking";
    }       
}

public class Cruze : Cars,Brake
{
    public override string GetBrakeTechnology()
    {
       return "I use EBD system for braking";
    }         
}

Бачите проблему у вищезгаданих двох класах? Вони успадковують з декількох класів, які C # .Net не дозволяє, навіть якщо метод реалізований у дітей. Тут виникає потреба в інтерфейсі.

interface IBrakeTechnology
{
    string GetBrakeTechnology();
}

А реалізація наведена нижче:

public class Verna : Cars, IBrakeTechnology
{
    public string GetBrakeTechnology()
    {
        return "I use ABS system for braking";
    }
}

public class Cruze : Cars, IBrakeTechnology
{
   public string GetBrakeTechnology()
   {
       return "I use EBD system for braking";
   }        
}

Тепер Верна і Круз можуть досягти багаторазового успадкування за допомогою власного виду гальмівних технологій за допомогою інтерфейсу.


4
Це одне з найкращих пояснень через приклади.
Адам Мендоса

2
Це має сенс для мене, не ламаючи мозок. Я просто намагався придумати приклад автомобіля для своїх студентів. Дякуємо, що вклали час, щоб це зробити разом.
tazboy

9

Інтерфейси - це легкий спосіб примусити певну поведінку. Це один із способів думати.


8

Ці відповіді занадто довгі.

  • Інтерфейси призначені для визначення поведінки.

  • Абстрактні заняття призначені для визначення самої речі, включаючи її поведінку. Ось чому ми іноді створюємо абстрактний клас з деякими додатковими властивостями, що успадковують інтерфейс.

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


7

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

2) Ви можете визначити властивість в інтерфейсі, тому клас, який реалізує цей інтерфейс, повинен мати це властивість.

Наприклад:

  public interface IVariable
  {
      string name {get; set;}
  }

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


7

Хоча це питання досить старе, я хотів би додати ще один момент на користь інтерфейсів:

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


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

6

З іншого мого відповіді , здебільшого я маю справу з тим, коли використовувати один проти іншого:

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


6

Типи інтерфейсу проти абстрактних базових класів

Адаптовано з Pro C # 5.0 та .NET 4.5 Framework .

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

public abstract class CloneableType
{
// Only derived types can support this
// "polymorphic interface." Classes in other
// hierarchies have no access to this abstract
// member.
   public abstract object Clone();
}

Враховуючи це визначення, лише члени, що розширюють CloneableType, можуть підтримувати метод Clone (). Якщо ви створюєте новий набір класів, які не розширюють цей базовий клас, ви не можете отримати цей поліморфний інтерфейс. Також ви можете згадати, що C # не підтримує багатократне успадкування для класів. Тому, якщо ви хотіли створити MiniVan, який є - Автомобілем і є - CloneableType, ви не можете цього зробити:

// Nope! Multiple inheritance is not possible in C#
// for classes.
public class MiniVan : Car, CloneableType
{
}

Як ви здогадалися, на допомогу приходять типи інтерфейсів. Після того, як буде визначено інтерфейс, він може бути реалізований будь-яким класом або структурою, в будь-якій ієрархії, в будь-якому просторі імен або будь-якій збірці (написаний будь-якою мовою програмування .NET). Як бачите, інтерфейси дуже поліморфні. Розглянемо стандартний інтерфейс .NET з ім'ям ICloneable, визначений у просторі імен системи. Цей інтерфейс визначає єдиний метод під назвою Clone ():

public interface ICloneable
{
object Clone();
}

6

Відповідь на друге питання: publicзмінна, визначена в, interfaceє static finalза замовчуванням, тоді як publicзмінна в abstractкласі є змінною екземпляра.


6

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

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

Інтерфейс:

Реч або обставина, яка дозволяє окремим, а іноді і несумісним елементам ефективно координувати.

Анотація:

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

Приклад:

Ви купили машину і їй потрібно паливо.

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

Ваша модель автомобіля - XYZце жанр ABC, тому це конкретний автомобіль, конкретний екземпляр автомобіля. Автомобіль не є реальним об’єктом. Насправді це абстрактний набір стандартів (якостей) для створення конкретного об’єкта. Коротше кажучи, Авто - це абстрактний клас , це "щось, що концентрує в собі сутнісні якості чогось більш обширного або загального" .

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

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

Додаток

Крім того, я думаю, ви повинні пам’ятати про значення терміна клас, який є (з того самого сайту, про який було сказано раніше):

Клас:

Ряд осіб або речей, які розглядаються як такі, що формують групу за загальними ознаками, характеристиками, якостями чи рисами; добрий;

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


1
занадто багато пуху, не робіть для людей це більш заплутаним, ніж це можливо.
ganjeii

5

З точки зору кодування

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

З точки зору дизайну

Зберігайте його як абстрактний клас, якщо це відносини "Є" і вам потрібен підмножина або вся функціональність. Зберігайте це як інтерфейс, якщо це стосунки "Слід робити".

Вирішіть, що вам потрібно: просто застосування політики або повторної використання коду та політики.


3

Пара інших відмінностей:

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

Так що ви можете використовувати абстрактний клас самостійно, навіть якщо він ніколи не реалізований (через статичні члени) і не можете використовувати інтерфейс самостійно.


в Java, інтерфейс може мати змінну учасника, але за замовчуванням вони стають загальнодоступними статичними .. тому інтерфейс може мати статичні поля
Jitendra Vispute

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