Мені ще років від того, щоб повністю зрозуміти відмінність між абстрактним класом та інтерфейсом. Кожен раз, коли я думаю, що я отримую ручку щодо основних понять, я переглядаю stackexchange і я два кроки назад. Але декілька думок на тему та питання ОП:
Спочатку:
Є два поширених пояснення інтерфейсу:
Інтерфейс - це перелік методів та властивостей, які може впроваджувати будь-який клас, а впроваджуючи інтерфейс, клас гарантує, що ці методи (та їх підписи), а ці властивості (та їх типи) будуть доступні при "взаємодії" з цим класом або об'єкт цього класу. Інтерфейс - це договір.
Інтерфейси - це абстрактні класи, які нічого не можуть / не можуть зробити. Вони корисні, тому що ви можете реалізувати декілька, на відміну від середніх батьківських класів. Мовляв, я можу бути об’єктом класу BananaBread і успадковувати від BaseBread, але це не означає, що я не можу також реалізувати як IWithNuts, так і інтерфейси ITastesYummy. Я навіть міг реалізувати інтерфейс IDoesTheDishes, бо я не просто хліб, знаєте?
Існує два поширених пояснення абстрактного класу:
Абстрактний клас, знаєте, річ не те, що річ може зробити. Це як, по суті, зовсім не справжня річ. Почекай, це допоможе. Човен - це абстрактний клас, але сексуальна яхта Playboy була б підкласом BaseBoat.
Я читав книгу про абстрактні класи, і, можливо, ви повинні прочитати цю книгу, тому що ви, мабуть, не зрозумієте її і зробите це неправильно, якщо ви не прочитали цю книгу.
До речі, книга Цитри завжди здається вражаючою, навіть якщо я все ще йду розгубленою.
Друге:
Щодо того, хтось запитав простішу версію цього питання, класичну, "навіщо використовувати інтерфейси? Яка різниця? Що я пропускаю?" І в одній відповіді простий приклад використав пілот ВПС. Це не зовсім суттєво, але це викликало чудові коментарі, один з яких згадував про інтерфейс IFlyable, що має такі методи, як takeOff, pilotEject тощо. І це дійсно натиснуло на мене як на прикладі реального світу, чому інтерфейси не просто корисні, але вирішальне значення Інтерфейс робить об'єкт / клас інтуїтивно зрозумілим або, принаймні, дає сенс, який він є. Інтерфейс не на користь об'єкта чи даних, а на те, що потрібно взаємодіяти з цим об’єктом. Класичний Фрукт-> Яблуко-> Фуджі або Форма-> Трикутник-> Рівносторонні приклади успадкування є чудовою моделлю для таксономічного розуміння даного об’єкта на основі його нащадків. Він інформує споживача та процесори про його загальні якості, поведінку, чи об’єкт є групою речей, буде шланг вашої системи, якщо ви поставите її в неправильному місці, або описує сенсорні дані, роз'єм до певного сховища даних або фінансові дані, необхідні для складання фонду оплати праці.
У конкретному об'єкті Plane може бути, а може і не бути методу аварійної посадки, але я буду злий, якщо я припускаю його аварійну землю, як і будь-який інший перельотний об'єкт, тільки щоб прокинутися охопленим в DumbPlane і дізнатися, що розробники пішли з quickLand бо вони думали, що це все одно. Так само, як я був би розчарований, якби кожен виробник шнеків мав власну інтерпретацію, або якщо на моєму телевізорі не було кнопки збільшення гучності вище кнопки зменшення гучності.
Абстрактні класи - це модель, яка встановлює те, що повинен мати будь-який нащадковий об'єкт, щоб бути таким класом. Якщо у вас немає всіх якостей качки, неважливо, що у вас реалізований інтерфейс IQuack, ваш просто дивний пінгвін. Інтерфейси - це те, що має сенс навіть тоді, коли ви не можете бути впевнені ні в чому іншому. Джефф Голдблум та Starbuck обидва змогли літати на чужих космічних кораблях, оскільки інтерфейс був надійно схожим.
Третє:
Я погоджуюся з вашим колегою, адже іноді потрібно застосувати певні методи на самому початку. Якщо ви створюєте ORM активного запису, йому потрібен метод збереження. Це не до підкласу, який можна інстанціювати. І якщо інтерфейс ICRUD є достатньо портативним, щоб не бути пов'язаний виключно з одним абстрактним класом, він може бути реалізований іншими класами, щоб зробити їх надійними та інтуїтивними для всіх, хто вже знайомий з будь-яким із класів нащадків цього абстрактного класу.
З іншого боку, раніше був чудовий приклад, коли не переходити до прив’язки інтерфейсу до абстрактного класу, оскільки не всі типи списку (або повинні) реалізувати інтерфейс черги. Ви сказали, що цей сценарій трапляється вдвічі, а це означає, що ви та ваш колега помиляєтесь половину часу, і, отже, найкраще зробити це сперечатися, обговорювати, вважати, і якщо вони виявляться правильними, визнайте та приймайте зв'язок . Але не робіть розробника, який дотримується філософії, навіть коли це не найкраще для роботи.