Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Що означає «композиція замість успадкування» і коли успадкування все ж доречне?

Успадкування повторно використовує код через ієрархію «є різновидом» (Admin extends User). Композиція - через «має» чи «використовує»: об'єкт отримує інші об'єкти й делегує їм роботу.

Проблеми глибокого успадкування:

class Report { public function generate() { /* ... */ } }
class PdfReport extends Report { /* ... */ }
class CachedPdfReport extends PdfReport { /* ... */ }
class CachedEmailedPdfReport extends CachedPdfReport { /* ... */ }
// а потрібен ще CachedEmailedCsvReport...
  • комбінаторний вибух: кожна комбінація можливостей - новий клас;
  • крихкий базовий клас: зміна в Report непередбачувано ламає нащадків;
  • жорсткий зв'язок: нащадок залежить від внутрішніх деталей батька (protected), а не лише від публічного API;
  • одне успадкування в PHP: клас не може взяти поведінку з двох батьків.

Композицією:

final class ReportGenerator
{
    public function __construct(
        private ReportFormatter $formatter,     // Pdf чи Csv
        private ReportDelivery $delivery,       // Email чи Storage
        private CacheRepository $cache,
    ) {}

    public function run(ReportQuery $query): void
    {
        $data = $this->cache->remember($query->key(), 3600, fn () => $query->fetch());
        $this->delivery->send($this->formatter->format($data));
    }
}

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

Інструменти композиції: впровадження залежностей, Strategy, Decorator (обгортання з тим самим інтерфейсом), делегування.

Трейти PHP - механізм повторного використання коду без успадкування, але це радше «копіювання методів» у клас: вони не створюють окремих об'єктів і можуть мати ті самі проблеми прихованих залежностей. Добрі для невеликої поведінки (HasFactory, SoftDeletes), погані як заміна архітектури.

Коли успадкування доречне:

  • справжнє відношення «є різновидом», де нащадок повністю замінює батька (принцип Лісков);
  • точки розширення фреймворку: extends Model, extends Controller, extends Command - фреймворк так спроєктований;
  • абстрактний клас з невеликою спільною логікою і шаблонним методом;
  • неглибока ієрархія (1-2 рівні).

Корисне правило: класи за замовчуванням final. Відкривати для успадкування - свідоме рішення, а не випадковість.

Докладніше в документації: Композиція замість успадкування

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання