Чим відрізняються успадкування та композиція в Java
Незважаючи на те, що і композиція, і наслідування дозволяють використовувати код повторно, вони роблять це по-різному. Основна відмінність між ними полягає в тому, що композиція дозволяє використовувати код без його розширення. Спадкування при цьому потребує розширення існуючого класу. Інша важлива відмінність: при композиції ми можемо повторно використовувати код навіть із final-класу, тоді як успадковуватись від нього неможливо. Крім того, при композиції можливе використання коду з декількох різних класів. З успадкуванням такий трюк не спрацює: Java не підтримується множинне успадкування. Зате ви можете зробити це C++. До речі, завжди варто віддавати перевагу композиції успадкування в Java. І не тільки тому, що так радить Джошуа Блох у своїй книзі Effective Java (яка є відмінним джерелом корисних порад для Java-програміста). Аргументи за використання композиції ви можете прочитати тут.
Спадкування та композиція
Давайте подивимося детальніше на відмінності композиції та успадкування. Ми розглянемо кожен пункт докладно, але без нудних деталей.
Перша відмінність стосується гнучкості коду. При використанні наслідування ви повинні описати, який клас ви розширюєте. При цьому ви не можете замінити його під час виконання програми. Використовуючи композицію, ви можете визначити тип, що використовується, який може містити кілька різних реалізацій. Таким чином, композиція надає набагато більше гнучкості, ніж спадкування.
Обмежене повторне використання коду при наслідуванні
Важливий аргумент при виборі способу повторного використання коду полягає в тому, що класи, розширені за допомогою композиції, легше тестувати, оскільки ви завжди можете надати заглушку для використовуваногокласу. При наслідуванні вам знадобиться батьківський клас для тестування, і замінити його заглушкою не вдасться.
Final-класи
Неможливість розширити final-класи – ще одне обмеження наслідування. У Java немає можливості успадковуватись від final-класів, тому знову єдиний вихід - використовувати композицію для повторного використання коду.
Інкапсуляція
Остання відмінність композиції та успадкування в Java полягає в їхньому відношенні до інкапсуляції. Незважаючи на те, що та та інша техніки дозволяють повторно використовувати код, успадкування порушує принцип інкапсуляції, оскільки підклас залежить від поведінки батьківського класу. Якщо клас-батько змінить свою поведінку, це вплине і на його нащадків. Якщо класи погано документовані і клас-нащадок неправильно використовує батьківський, то за будь-якої зміни батька функціональність нащадка виявиться зламаною. Для того, щоб побачити це на прикладі, ви можете прочитати розділи 16 та 17 Effective Java.
Ось і все, що можна сказати про відмінності композиції та успадкування в Java та в об'єктно-орієнтованому програмуванні взагалі. Як бачите, вони по-різному є однією метою: повторне використання перевірених і протестованих ділянок коду. Композиція при цьому дозволяє захистити клас, що повторно використовується, від клієнтів, тоді як успадкування цього не гарантує. Тим не менш, іноді спадкування необхідне. Зокрема коли ви створюєте класи з одного сімейства.