LSP means that objects of a parent class should be replaceable with objects of a child class without changing the correctness of the program.Liskov Substitution Principle in LLD - Cheat Sheet & Quick Revision
Practice
What does the Liskov Substitution Principle (LSP) primarily ensure in system design?
Solution
Step 1: Understand LSP definition
LSP states that objects of a child class should be replaceable with objects of the parent class without breaking the program.Step 2: Analyze options against LSP
Only Child classes can replace parent classes without affecting correctness correctly describes this principle. Other options contradict LSP or are unrelated.Final Answer:
Child classes can replace parent classes without affecting correctness -> Option AQuick Check:
Liskov Substitution Principle = Child replaces Parent [OK]
- Thinking LSP forbids inheritance
- Confusing LSP with interface segregation
- Believing child classes can change parent behavior arbitrarily
Which of the following class declarations follows the Liskov Substitution Principle?
class Bird {
fly() {}
}
class Penguin extends Bird {
fly() {
throw new Error('Cannot fly');
}
}Solution
Step 1: Analyze Penguin's fly method
Penguin throws an error on fly(), but Bird expects fly() to work normally.Step 2: Check LSP compliance
Since Penguin cannot be used where Bird is expected (fly method fails), it violates LSP.Final Answer:
No, because Penguin breaks expected behavior of Bird -> Option BQuick Check:
Child must not break parent behavior = No [OK]
- Ignoring method behavior changes in child
- Assuming inheritance alone guarantees LSP
- Thinking overriding with error is allowed
Consider the following code snippet. What will be the output?
class Vehicle {
start() { return 'Vehicle started'; }
}
class Car extends Vehicle {
start() { return 'Car started'; }
}
function startVehicle(v) {
return v.start();
}
const myCar = new Car();
console.log(startVehicle(myCar));Solution
Step 1: Understand method overriding
Car overrides start() method to return 'Car started'.Step 2: Trace function call
startVehicle(myCar) calls myCar.start(), which returns 'Car started'.Final Answer:
'Car started' -> Option CQuick Check:
Overridden method returns child's message [OK]
- Expecting parent method output instead of child's
- Confusing method names or forgetting override
- Assuming error due to polymorphism
Identify the violation of Liskov Substitution Principle in the code below and select the fix.
class Rectangle {
setWidth(w) { this.width = w; }
setHeight(h) { this.height = h; }
area() { return this.width * this.height; }
}
class Square extends Rectangle {
setWidth(w) {
this.width = w;
this.height = w;
}
setHeight(h) {
this.width = h;
this.height = h;
}
}Solution
Step 1: Identify LSP violation
Square changes behavior of setWidth and setHeight, breaking Rectangle's expectations.Step 2: Choose fix
To follow LSP, Square and Rectangle should not be in inheritance relation if behaviors differ fundamentally.Final Answer:
Use separate classes without inheritance for Square and Rectangle -> Option AQuick Check:
Different behavior means no inheritance [OK]
- Ignoring behavioral changes in overridden methods
- Trying to fix by only overriding area()
- Assuming inheritance always fits shapes
You are designing a payment system with a base class PaymentMethod and subclasses CreditCard and Bitcoin. The base class has a method processPayment(amount) that returns a success message. However, Bitcoin payments require additional confirmation steps and may fail differently. How should you design these classes to follow the Liskov Substitution Principle?
Solution
Step 1: Understand LSP in payment context
Subclasses must behave so they can replace base class without breaking client code.Step 2: Design consistent behavior
Bitcoin and CreditCard should implement processPayment so it returns success/failure in a consistent way, hiding internal differences.Final Answer:
Keep Bitcoin and CreditCard as subclasses but ensure processPayment behaves consistently and returns success/failure uniformly -> Option DQuick Check:
Consistent behavior across subclasses = LSP compliance [OK]
- Throwing errors breaking expected method contracts
- Ignoring different failure modes without abstraction
- Removing inheritance unnecessarily
Ready to prove it?
Pass the test and this pattern moves unknown
