Які відмінності між абстрактними класами, інтерфейсами та коли ними користуватися


15

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

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

Ось два класи, які я створив:

class Ad {
    $title;
    $description
    $price;

    function get_data($website){  }

    function validate_price(){  }
 }


class calendar_event {
    $title;
    $description

    $start_date;

    function get_data($website){ //guts }

    function validate_dates(){ //guts }
 }

Отже, як ви бачите, ці класи майже однакові. Тут не показано, але є й інші функції like get_zip(), save_to_database()які є загальними для моїх класів. Я також додав інші класи Автомобілі та Домашні тварини, які мають всі загальні методи і, звичайно, властивості, характерні для цих класів (наприклад, пробіг, вага).

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

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

abstract class content {
    $title;
    $description


    function get_data($website){  }

    function common_function2() { }
    function common_function3() { }
 }


class calendar_event extends content {

    $start_date;

    function validate_dates(){  }
 }

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

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

Спасибі!


В Інтернеті є багато хороших прикладів. Я думаю, що це один з них. javapapers.com/core-java/ab абстракт-and-interface-core-java-2/…
Siva

Відповіді:


26

Простіше кажучи:

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

Анотація (а також конкретні) класи призначені для «є» видом відносин.

Подивіться на ці приклади:

class Bird extends Animal implements Flight;
class Plane extends Vehicle implements Flight, AccountableAsset;
class Mosquito extends Animal implements Flight;
class Horse extends Animal;
class RaceHorse extends Horse implements AccountableAsset;
class Pegasus extends Horse implements Flight;

Bird, Mosquitoі Horse є Animals . Вони пов'язані між собою. Вони успадковують поширені методи від тварин, подібних до тварин eat(), metabolize() and reproduce(). Можливо, вони переосмислюють ці методи, додаючи їм трохи зайвого, але вони скористаються поведінкою за замовчуванням, реалізованою в Animal, якmetabolizeGlucose().

Planeне пов'язане з Bird, Mosquitoабо Horse.

Flightреалізується різними, неспорідненими класами, як Birdі Plane.

AccountableAssetтакож реалізується різними, неспорідненими класами, як Planeі RaceHorse.

Horse не реалізує політ.

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

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

Наприклад, ви можете мати суми програми значення групи, AccountableAssetsнезалежно від їхнього існування RaceHorsesабо Planes.


Дивовижний. Інтерфейс забезпечує певний розділ функціональності, який накладає can do/can be treated asтам, де абстрактні класи діють як основоположні!
Abhiroj Panwar

13

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

Інтерфейси визначають загальний контракт. Наприклад, інтерфейс під назвою IAnimal, де всі тварини діляться такими функціями, як Eat (), Move (), Attack () тощо. Хоча всі вони мають однакові функції, всі або більшість з них мають різний спосіб (реалізацію) досягнення це.

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

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

Крім того, схоже, що в Google не вистачає результатів.


3

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

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

Сподіваюся, що це допомагає, але є багато інформації про це в Інтернеті, Лео


2
Classes cannot have multiple inheritance- Вірно для таких мов, як Java та C #, не відповідає C ++.
Роберт Харві

3

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

Інтерфейси дозволяють повторно використовувати код клієнта з різними реалізаціями. Клієнт класу get_data ($ website) не переймається пунктами $ title або $ description. Він просто хоче доручити вашому вмісту завантажувати дані. Якщо у вас є різні типи вмісту, для деяких потрібен $ опис, а якийсь немає, ви можете надати клас ContentInterface, який визначає лише підпис ваших дочірніх класів. Тепер клієнт може мати будь-яку кількість різних змістів, не знаючи, як саме вони працюють. Лиск принцип заміщення хороша річ , щоб прочитати про вивчити цю ідею. Мені також подобається написання дядька Боба на цю тему. Інтерфейси дуже важливі для тестування одиниць, а створення інтерфейсів - це хороша звичка вчитися.

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

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


3

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

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

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


-3
  1. Основна відмінність полягає в тому, що методи інтерфейсу Java неявно абстрактні і не можуть мати реалізації. Абстрактний клас Java може мати методи екземплярів, які реалізують поведінку за замовчуванням.
  2. Змінні, оголошені в інтерфейсі Java, за замовчуванням є остаточними. Абстрактний клас може містити не остаточні змінні.
  3. Члени інтерфейсу Java за замовчуванням є загальнодоступними. Абстрактний клас Java може мати звичайні смаки для членів класу, як приватні, захищені тощо.
  4. Інтерфейс Java повинен бути реалізований за допомогою ключового слова "tools"; Абстрактний клас Java слід розширити за допомогою ключового слова "extends".
  5. Інтерфейс може розширювати інший інтерфейс Java, лише абстрактний клас може розширювати інший клас Java та реалізовувати декілька Java-інтерфейсів.
  6. Клас Java може реалізовувати декілька інтерфейсів, але він може розширювати лише один абстрактний клас.
  7. Інтерфейс абсолютно абстрактний і його неможливо встановити; Абстрактний клас Java також не може бути ініційованим, але його можна викликати, якщо існує main ().
  8. У порівнянні з абстрактними класами java, інтерфейси java повільні, оскільки це вимагає додаткової непрямості.
  9. Інтерфейс і абстрактний клас на Java полягає в тому, що ви не можете створити неабразований метод в інтерфейсі, кожен метод в інтерфейсі за замовчуванням є абстрактним, але ви можете створити не абстрактний метод в абстрактному класі.
  10. Абстрактний клас проти інтерфейсу на Java полягає в тому, що інтерфейси краще підходять для оголошення типу, а абстрактний клас більше підходить для повторного використання коду та перспективи еволюції.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.