Skip to main content

Command Palette

Search for a command to run...

Mastering "L" in S.O.L.I.D

Liskov Substitution Principle

Updated
2 min read
Mastering "L" in S.O.L.I.D

“Objects of a superclass should be replaceable with objects of its subclasses without breaking the application’s behavior.”

💡 Real-Life Example

Think of this:

  • You have a class Bird that can fly().

  • You create a subclass Sparrow (it can fly ✅).

  • Then you create another subclass Ostrich (it cannot fly ❌).

If your program expects all Birds to fly, using Ostrich will break your logic — which violates LSP.

So, Ostrich should not extend Bird if Bird assumes “can fly”.

// ❌ Violates LSP
class Bird {
    void fly() {
        System.out.println("Flying...");
    }
}

class Sparrow extends Bird {}  // OK
class Ostrich extends Bird {   // Problem
    @Override
    void fly() {
        throw new UnsupportedOperationException("Ostrich can't fly!");
    }
}

// ✅ Correct Approach
interface Bird {}
interface FlyingBird extends Bird {
    void fly();
}

class Sparrow implements FlyingBird {
    public void fly() {
        System.out.println("Flying...");
    }
}

class Ostrich implements Bird {
    // Ostrich doesn't fly, but still a bird — no LSP violation.
}

More Examples:-

🧾 1. Payment System Example (E-commerce App)

Imagine you have a PaymentService interface that processes payments.

You have classes like:

  • CreditCardPayment

  • PayPalPayment

  • UPIPayment

Each one should behave like a payment service — if one fails to behave differently (e.g., throws error on same method), it violates LSP.

interface PaymentService {
    void pay(double amount);
}

class CreditCardPayment implements PaymentService {
    public void pay(double amount) {
        System.out.println("Paid " + amount + " using Credit Card");
    }
}

class PayPalPayment implements PaymentService {
    public void pay(double amount) {
        System.out.println("Paid " + amount + " using PayPal");
    }
}

// ❌ Violating LSP
class CashOnDeliveryPayment implements PaymentService {
    public void pay(double amount) {
        throw new UnsupportedOperationException("Cash payment not supported online!");
    }
}

Here, CashOnDeliveryPayment breaks LSP because it cannot be used wherever a PaymentService is expected.
It will crash the program.

Fix: Don’t force it into the same inheritance; maybe separate interfaces:

interface OnlinePaymentService extends PaymentService {}
interface OfflinePaymentService {
    void collectCash();
}

📦 2. Inventory System Example

🔹 English:

Suppose your app has a base class InventoryItem.
You create child classes like:

  • PerishableItem (milk, fruits)

  • NonPerishableItem (phone, laptop)

If the parent class has a method like calculateExpiryDate(), and non-perishable items can’t have expiry, that’s an LSP violation.

✅ Fix → Move expiry logic to a subclass or new interface.