JavaRush/Java блог/Random UA/10 питань щодо абстрактних класів та інтерфейсів із співб...

10 питань щодо абстрактних класів та інтерфейсів із співбесід з Java

Стаття з групи Random UA
учасників
Абстрактні класи та інтерфейси дуже популярні у всіх об'єктно-орієнтованих мовах програмування. І практично на кожній співбесіді з Java трапляється хоча б одне питання на цю тему. Інтерфейси згадуються частіше, через їхню популярність серед проектувальників ПЗ, але іноді зустрічаються й питання абстрактних класів. Останні найчастіше задають претендентам на посаду джуніор-розробників, скажімо, з не більше ніж дворічним досвідом розробки на Java, тоді як питання щодо інтерфейсів найчастіше зустрічаються при співбесіді тих, чий досвід уже перевалив за чотири роки. В основному, їх задають разом з іншими питаннями з патерн проектування Java, наприклад, з патерн Decorator (Декоратор) або Factory (Фабрика). 10 питань щодо абстрактних класів та інтерфейсів із співбесід з Java - 1У цій статті ми розглянемо часті питання щодо абстрактних класів та інтерфейсів, які задавалися на співбесідах з Java різного рівня. Більшість з них не повинна представляти складності навіть для Java-програміста-початківця. В основному це питання на чисте знання, але деякі з них, наприклад, про відмінності між абстрактними класами та інтерфейсами Java або про те, коли краще віддати перевагу абстрактному класу інтерфейсу , можуть виявитися досить непростими. Пропонуємо вам десяток цікавих питань на тему.
Якщо вам коли-небудь задавали на співбесіді або доводилося ставити будь-яке питання про абстрактні класи та інтерфейси, але його в даному списку немає, ділитесь ним в коментарях.

1. Чи можуть у мові Java у абстрактного класу бути конструктори?

Так, в абстрактному класі Java можна оголосити і визначити конструктори. Оскільки створювати екземпляри абстрактних класів не можна, викликати такий конструктор можна лише за формуванні ланцюжка конструкторів, тобто за створення екземпляра конкретного класу-реализации. Але уявіть, що інтерв'юер запитає потім: а який сенс у конструкторі, якщо створити екземпляр абстрактного класу все одно не можна? Справа в тому, що його все одно можна використовувати для завдання початкових значень загальних змінних, оголошених в абстрактному класі та використовуваних різними реалізаціями. Навіть якщо ви не оголосабо жодного конструктора, компілятор додасть до абстрактного класу конструктор за умовчанням без аргументів. Без нього ваш підклас не скомпілюється, оскільки перший оператор у будь-якому конструкторі є неявним викликом.super()– конструктора суперкласу за замовчуванням у Java.

2. Чи можуть абстрактні класи у мові Java реалізовувати інтерфейси? Чи вони реалізовувати всі методи?

Так, абстрактні класи можуть реалізовувати інтерфейси за допомогою ключового слова implements. Оскільки вони абстрактні, то мають реалізовувати всі методи. Наявність абстрактного базового класу та інтерфейсу для оголошення типу є рекомендованою практикою. Приклад - інтерфейс java.util.Listта відповідний абстрактний клас java.util.AbstractList. Оскільки AbstractListреалізує всі загальні методи, то конкретні реалізації (наприклад, LinkedListі ArrayList) не повинні реалізувати всі методи, як у випадку, якби вони реалізували Listбезпосередньо інтерфейс. Це рішення поєднує перевагу використання інтерфейсу для оголошення типу та гнучкість абстрактного класу для реалізації всієї загальної поведінки в одному місці. У книзі Джошуа Блох «Java. Ефективне програмування»Існує чудова глава на тему використання інтерфейсів і абстрактних класів в Java, для кращого розуміння має сенс її вивчити.

3. Чи може бути абстрактний клас бути final?

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

4. Чи можуть у абстрактного класу у мові Java бути статичні методи?

Так, абстрактні класи можуть оголошувати та визначати статичні методи. Тільки необхідно дотримуватися загальних принципів створення статичних методів Java, оскільки вони небажані при об'єктно-орієнтованому проектуванні, адже перевизначення статичних методів Java неможливо. Статичні методи в абстрактному класі – явище дуже рідкісне, але якщо на це є поважні причини, вам нічого не завадить їх використовувати.

5. Чи можна створити екземпляр абстрактного класу?

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

6. Чи обов'язково в абстрактному класі мають бути абстрактні методи?

Ні, в абстрактному класі може бути жодного абстрактного методу. Зробити клас абстрактним у мові Java можна просто, використовуючи ключове слово abstractпри оголошенні. Компілятор забезпечить виконання всіх структурних обмежень, наприклад, заборони створення екземплярів цього класу. До речі, питання, чи мають бути абстрактні методи в абстрактному класі чи інтерфейсі – спірне. Мені видається, що в абстрактному класі мають бути абстрактні методи, оскільки це перше, про що думає програміст, бачачи абстрактний клас. Це добре узгоджується із принципом мінімізації несподіванок.

7. Які відмінності між абстрактним класом та інтерфейсом у Java?

Це найважливіше і одне з класичних питань на співбесідах з мови Java. Я не можу порахувати, скільки разів зустрічав це питання на співбесідах з Java для всіх рівнів. Цікавим це питання робить, зокрема, можливість для претендента надати приклад. Відповідати на питання з основ об'єктно-орієнтованого програмування, наприклад, розповісти про абстракцію, інкапсуляцію, поліморфізм і успадкування, легко, але коли справа доходить до подібних тонких нюансів, претенденти на посаду дуже часто губляться і кажуть, що перше спадає на думку. Відповідь на це питання тягне на окрему статтю (особливо після змін у Java 8), проте якщо коротко:
  • Інтерфейс описує лише поведінку (методи) об'єкта, тоді як станів (полів) в нього немає (крім public static final), тоді як в абстрактного класу може бути.

  • Абстрактний клас успадковується (extends), а інтерфейс – реалізується (implements). Ми можемо успадкувати лише один клас, а реалізувати інтерфейсів – скільки завгодно. Інтерфейс може наслідувати (extends) інший інтерфейс/інтерфейси.

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

8. Коли має сенс віддати перевагу абстрактному класу інтерфейсу і навпаки?

Це продовження попередніх питань щодо абстрактних класів та інтерфейсів. Якщо ви знаєте, які їх синтаксичні відмінності, то відповідь на це питання не доставить вам проблем, оскільки саме вони є визначальним фактором прийняття рішення. Оскільки до опублікованого інтерфейсу практично неможливо додати новий метод, у разі потенційної необхідності доопрацювання краще використовувати абстрактний клас. Розвивати абстрактні класи в Java простіше, ніж інтерфейси. Аналогічно, якщо в інтерфейсі занадто багато методів і реалізація їх стає справжнім головним болем, краще створити абстрактний клас для реалізації за умовчанням. Цьому патерну випливають і в пакеті колекцій Java, абстрактний клас AbstractListзабезпечує реалізацію за умовчанням для інтерфейсу List. Використовуйте абстрактні класи, якщо:
  • Ви хочете поділитися кодом між кількома тісно пов'язаними класами.

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

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

  • Ви хочете визначити поведінку конкретного типу даних, але вам не важливо, хто її реалізує.

  • Ви хочете використовувати множинне наслідування типу.

9. Що таке абстрактний метод у мові Java?

Абстрактний метод – це метод без тіла. Ви просто повідомляєте метод, не визначаючи його, з використанням ключового слова abstractв оголошенні методу. Усі оголошені всередині інтерфейсу у мові Java методи – за умовчанням абстрактні. Ось приклад абстрактного методу у мові Java:
public void abstract printVersion();
Тепер для реалізації цього методу необхідно розширити абстрактний клас і цей метод перевизначити.

10. Чи може абстрактний клас у Java містити метод main?

Так, абстрактний клас Java може містити метод main, адже це просто ще один статичний метод, і абстрактний клас можна виконувати за допомогою методу main, якщо не створювати його екземплярів. Ось і все, що я хотів розповісти. І пам'ятайте: абстрактні класи та інтерфейси – ключові проектні рішення в процесі об'єктно-орієнтованого аналізу та проектування, і застосовувати їх слід з обачністю, звичайно, якщо ви хочете створити гнучку систему.
Коментарі
  • популярні
  • нові
  • старі
Щоб залишити коментар, потрібно ввійти в систему
Для цієї сторінки немає коментарів.