SYS ARCHITECTLearning Platform
Settings
Theory

Liskov Substitution Principle (LSP)

📋 Overview

The Liskov Substitution Principle (LSP) is the "L" in SOLID. It states that objects of a superclass should be replaceable with objects of its subclasses without affecting the correctness of the program. If a function works with a Bird class, it must work perfectly with an Ostrich or Penguin without checking if (bird instanceof Ostrich).


🏗️ Core Principles & Characteristics

  • The Contract: A subclass must honor the behavioral contract of its parent. This includes:
    • Pre-conditions: Cannot be strengthened in a subclass (you can't require more than the parent).
    • Post-conditions: Cannot be weakened in a subclass (you can't guarantee less than the parent).
  • Signature Compatibility: Methods must accept the same (or broader) types and return the same (or narrower) types.
  • Exception Safety: A subclass should not throw new, unexpected checked exceptions that the caller doesn't know how to handle.

⚖️ Trade-offs: Pros & Cons

  • Pros:
    • Polymorphism: Enables truly generic code that doesn't need to know concrete types.
    • Maintainability: Changes in subclasses don't ripple through the entire codebase.
    • Predictability: Reduces "surprises" during runtime.
  • Cons:
    • Inflexible Hierarchies: Can make deep inheritance trees difficult to design.
    • Boilerplate: Often requires splitting classes into multiple interfaces to satisfy specific behaviors (e.g., Flyable, Swimmable).

🌍 Real-World Implementation

  • Java Collections: You can swap an ArrayList for a LinkedList in any method accepting a List, and the application logic will remain correct (though performance may change).
  • Database Drivers: An application written for a generic SQLDriver should work with PostgreSQLDriver or MySQLDriver without modification, provided they adhere to the driver interface.
  • Payment Gateways: A PaymentProcessor base class can be substituted by StripeProcessor or PayPalProcessor seamlessly.

💡 Interview "Gotchas" & Tips

  • The "Classic" Rectangle-Square Problem: This is the #1 interview question. A Square is a Rectangle mathematically, but if a Rectangle has a setHeight(h) and setWidth(w) method, a Square violates LSP because setting the height will unexpectedly change the width. Solution: Use composition or separate them into a Shape interface.
  • "Ask for Forgiveness" (Exceptions): If you find yourself throwing UnsupportedOperationException in a subclass (e.g., Ostrich.fly()), you are almost certainly violating LSP.
  • Type Checking: If you see if (obj instanceof SubClass) in your logic, it's a "code smell" indicating that your abstraction isn't substitutable.

📐 Suggested Architecture Primitives

  • Interface Segregation: Break down fat classes into small, behavioral interfaces (e.g., Reader, Writer).
  • Composition over Inheritance: Instead of Ostrich extends Bird, use a Bird class that has a MovementStrategy (which could be WalkingStrategy or FlyingStrategy).
  • Design by Contract (DbC): Using tools or comments to strictly define what a method requires and what it guarantees.
Canvas