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

Як позбутися довгого switch за типом об'єкта?

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

function fee(Payment $p): int
{
    return match ($p->method) {
        'card' => (int) ($p->amount * 0.025),
        'bank_transfer' => 500,
        'cash' => 0,
    };
}
// і ще схожі match для label(), isRefundable(), icon()...

Варіант 1 - enum з методами (PHP 8.1+). Добре, коли поведінка невелика й залежить лише від типу:

enum PaymentMethod: string
{
    case Card = 'card';
    case BankTransfer = 'bank_transfer';
    case Cash = 'cash';

    public function fee(int $amount): int
    {
        return match ($this) {
            self::Card => (int) ($amount * 0.025),
            self::BankTransfer => 500,
            self::Cash => 0,
        };
    }
}

Знання про тип зібране в одному місці, а match без default змусить обробити новий випадок - інакше UnhandledMatchError, а статичний аналізатор попередить ще раніше.

Варіант 2 - поліморфізм (класи за спільним інтерфейсом). Коли в кожного типу своя складна логіка чи залежності:

interface PaymentProcessor
{
    public function fee(int $amount): int;
    public function refund(Payment $payment): void;
}

final class CardProcessor implements PaymentProcessor { /* ... */ }

Вибір реалізації - один раз, у фабриці чи контейнері. Далі код викликає методи без розгалужень.

Коли switch нормальний: він трапляється в одному місці (наприклад, у фабриці, що створює потрібний об'єкт), варіантів мало і їхній список стабільний. Поліморфізм заради одного if - зайве ускладнення.

Докладніше в документації: Replace Conditional with Polymorphism

Перевір себе

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

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