🧠 Interface vs Abstract Class w PHP — czym się różnią i kiedy używać?

W PHP często pojawia się pytanie:
kiedy użyć interfejsu, a kiedy klasy abstrakcyjnej?

Na pierwszy rzut oka robią podobne rzeczy — ale mają inne zastosowania.


🔹 Co to jest interfejs?

Interfejs (interface) to kontrakt, który mówi:

„każda klasa musi mieć te metody”

Nie zawiera logiki (poza wyjątkami w nowszym PHP), tylko definicje.

Przykład:

interface PaymentMethod {
public function pay(float $amount): void;
}

Klasa, która implementuje interfejs:

class CardPayment implements PaymentMethod {
public function pay(float $amount): void {
echo "Płacę kartą: $amount";
}
}

👉 Interfejs mówi CO ma być zrobione
👉 ale nie mówi JAK


🔸 Co to jest klasa abstrakcyjna?

Klasa abstrakcyjna (abstract class) to:

„szkielet klasy + częściowa implementacja”

Może mieć:

  • gotowe metody
  • właściwości
  • metody abstrakcyjne (do nadpisania)

Przykład:

abstract class Payment {
protected string $currency = 'PLN';

abstract public function pay(float $amount): void;

public function logPayment(float $amount): void {
echo "Log: $amount {$this->currency}";
}
}

Klasa dziedzicząca:

class BlikPayment extends Payment {
public function pay(float $amount): void {
echo "Płacę Blikiem: $amount";
}
}

👉 Klasa abstrakcyjna daje:

  • wspólną logikę
  • wspólny stan

⚔️ Interface vs Abstract Class — różnice

CechaInterfaceAbstract Class
Implementacja metod❌ (zazwyczaj brak)✅ może mieć
Właściwości
Dziedziczeniewiele interfejsówtylko jedna klasa
Celkontraktbaza + logika
Słowo kluczoweimplementsextends

🧠 Kiedy używać czego?

✅ Użyj interfejsu gdy:

  • chcesz narzucić strukturę
  • różne klasy robią to samo na różne sposoby
  • np. różne metody płatności, logowania, API

👉 przykład:

StripePayment, PayPalPayment, CryptoPayment

✅ Użyj klasy abstrakcyjnej gdy:

  • masz wspólną logikę
  • chcesz uniknąć duplikacji kodu
  • masz bazowy model systemu

👉 przykład:

BaseController, BaseRepository

🔥 Realny przykład z życia

System CRM:

  • interfejs:
interface Notification {
public function send(string $message): void;
}
  • implementacje:
EmailNotification
SMSNotification
SlackNotification

👉 każda działa inaczej, ale API jest wspólne


💡 TL;DR

  • interface = kontrakt
  • abstract class = baza + logika

🚀 Podsumowanie

Nie wybierasz „co lepsze”.

Wybierasz:

  • interface → gdy chcesz elastyczność
  • abstract class → gdy chcesz współdzielić kod

W dobrze zaprojektowanym systemie używasz… obu.