🔄 The LSP Rule
“Objects of a superclass should be replaceable with objects of its subclasses without breaking the application.”In simple terms: If you expect a Bird, any type of bird (Sparrow, Eagle, Parrot) should work the same way! The rental car analogy: When you rent a car, you expect it to have a steering wheel, pedals, and an ignition. Whether you get a Toyota Camry or a BMW 3 Series, the basic driving interface works the same. You would be shocked if you got a vehicle where pressing the brake made it accelerate. That is LSP: any subclass must honor the behavioral contract of its parent. The caller should never need to check “wait, which specific type did I get?” before using it safely.
🐧 The Famous Penguin Problem
The classic LSP violation:✅ The Correct Solution
📏 The Rectangle-Square Problem
Another famous LSP violation:❌ BAD: Square extends Rectangle
✅ GOOD: Separate Shapes
🎯 LSP Rules to Follow
Rule 1: Method Signatures
Child methods should accept the same or broader input types:Rule 2: Return Types
Child methods should return the same or narrower types:Rule 3: No New Exceptions
Children shouldn’t throw exceptions parents didn’t:Rule 4: Honor Invariants
If parent guarantees something, child must too:🎮 Real Example: File System
❌ BAD: ReadOnlyFile breaks File contract
✅ GOOD: Separate Interfaces
🐾 Real Example: Pet Store
🧪 Practice Exercise
Challenge: Fix the Employee Hierarchy
Challenge: Fix the Employee Hierarchy
This code violates LSP. Fix it!
📝 Quick LSP Checklist
Interview Insight
LSP is the hardest SOLID principle to demonstrate in interviews, but it creates the strongest impression when you do. The typical way it surfaces: you design a class hierarchy, and the interviewer probes an edge case. “What about a read-only user — can they inherit from User?” If the User parent class has a
save() method and ReadOnlyUser throws an exception on save, that is an LSP violation. The strong answer: “I would not make ReadOnlyUser extend User because it cannot honor the save() contract. Instead, I would create a Viewable interface that both share, and only give the writable path to full User objects.” The moment you use the phrase “honor the behavioral contract of the parent,” you signal deep understanding. The practical test: anywhere your code does isinstance checks to handle a specific subclass differently, that is a sign LSP might be violated — you are compensating for a subclass that does not truly substitute.🏃 Next: Interface Segregation Principle
Let’s learn why smaller, focused interfaces are better than big ones!Continue to Interface Segregation →
Learn why many small interfaces beat one big interface!