Bird
Raised Fist0
Interview Prepoop-design-patternsmediumAmazonGoogleFlipkartCREDRazorpay

Liskov Substitution Principle - Subtype Behavioural Contract

Choose your preparation mode3 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
🎯
Liskov Substitution Principle - Subtype Behavioural Contract
mediumOOPAmazonGoogleFlipkart

Imagine a payment system where a new payment method subclass breaks the expected behavior of the base payment interface, causing unexpected failures in the checkout process.

💡 Beginners often confuse LSP with just inheritance or method overriding, missing the subtlety that subtype objects must behave consistently with their base types to avoid breaking client code.
📋
Interview Question

Explain the Liskov Substitution Principle (LSP) and its importance as a behavioural contract for subtypes in object-oriented design. How does violating LSP affect software design?

Subtype substitutabilityBehavioural contracts in inheritanceCovariance and contravariance in method signatures
💡
Scenario & Trace
ScenarioA Rectangle class with width and height setters is extended by a Square subclass that overrides setters to keep width and height equal.
Client code expects to set width and height independently on a Rectangle object. When a Square instance is substituted, setting width changes height unexpectedly, violating client expectations and breaking the program logic.
ScenarioA Bird base class has a fly() method. A Penguin subclass inherits Bird but cannot fly.
Client code calls fly() on Bird references. Substituting a Penguin instance leads to unexpected behavior or exceptions, violating the behavioural contract that all Birds can fly.
  • Subtype narrows the range of acceptable input parameters → what happens to client code?
  • Subtype strengthens postconditions or invariants → how does this affect substitutability?
  • Covariant return types in overridden methods → when is this allowed or problematic?
⚠️
Common Mistakes
Confusing LSP with simple inheritance or polymorphism

Interviewer thinks candidate lacks understanding of behavioural contracts and substitutability

Emphasize that LSP is about preserving expected behavior, not just code reuse

Ignoring method preconditions and postconditions in subtype overrides

Candidate misses how contract violations cause runtime errors or logic bugs

Learn to analyze method contracts and ensure subtypes do not strengthen preconditions or weaken postconditions

Assuming overriding methods can arbitrarily change parameter types

Interviewer suspects candidate does not understand covariance and contravariance rules

Understand that parameter types must be contravariant or unchanged to maintain substitutability

Believing LSP only applies to method signatures, ignoring state invariants

Candidate misses that state changes can break substitutability even if signatures match

Recognize that subtypes must maintain all invariants of the base type to be substitutable

🧠
Basic Definition - What It Is
💡 This level covers the fundamental idea that subtypes must be replaceable for their base types without altering program correctness.

Intuition

A subtype should behave like its parent type so that clients using the parent type can use the subtype without surprises.

Explanation

The Liskov Substitution Principle states that objects of a superclass should be replaceable with objects of a subclass without affecting the correctness of the program. This means the subclass must honor the behavioural expectations set by the superclass. Violating this principle leads to fragile code where substituting a subtype breaks client code, causing bugs and maintenance headaches.

Memory Hook

💡 Think of a square peg fitting into a round hole: if it doesn’t fit as expected, it breaks the system.

Interview Questions

What does it mean if a subclass violates LSP?
  • Subclass objects cannot be used in place of superclass objects without errors
  • Client code relying on superclass behavior breaks
Depth Level
Interview Time30 seconds
Depthbasic

Covers the core definition and why it matters; sufficient for quick screening questions.

Interview Target: Minimum floor - never go below this

Knowing only this lets you pass initial interviews but won’t impress deeper technical rounds.

🧠
Mechanism Depth - How It Works
💡 This level explains the behavioural contract details and how method signatures and invariants affect substitutability.

Intuition

LSP enforces that subtype methods must accept the same or broader inputs and guarantee the same or stronger outputs and invariants as the base type.

Explanation

LSP is a behavioural contract that ensures subtypes preserve the expectations set by their supertypes. This involves several rules: preconditions cannot be strengthened (subtypes must accept all inputs the base type accepts), postconditions cannot be weakened (subtypes must fulfill all guarantees of the base type), and invariants must be maintained. Additionally, method signatures must be compatible, allowing covariance in return types but contravariance in parameter types. Violating these rules causes client code to fail or behave unpredictably when using subtype instances.

Memory Hook

💡 Think of a contract where the subtype promises to do everything the base type promises, no less and no more restrictive.

Interview Questions

How do preconditions and postconditions relate to LSP?
  • Subtypes cannot require more restrictive preconditions than supertypes
  • Subtypes must guarantee at least what supertypes guarantee in postconditions
  • Violating these breaks substitutability
Depth Level
Interview Time2-3 minutes
Depthintermediate

Demonstrates understanding of the behavioural contract and its implications on method design.

Interview Target: Target level for FAANG on-sites

Mastering this level distinguishes you from most candidates and shows deep OOP design knowledge.

📊
Explanation Depth Levels
💡 Choose your explanation depth based on interview stage and role expectations.
LevelInterview TimeSuitable ForRisk
Basic Definition30sScreening call or quick conceptual questionsToo shallow for on-site or design interviews
Mechanism Depth2-3 minutesOn-site interviews, design discussions, FAANG rolesRequires solid understanding; skipping details risks appearing superficial
💼
Interview Strategy
💡 Use this guide to structure your explanation clearly and confidently before interviews.

How to Present

Start with a clear definition of LSPGive a relatable example or analogyExplain the behavioural contract details including pre/postconditionsDiscuss common edge cases and consequences of violations

Time Allocation

Definition: 30s → Example: 1min → Mechanism: 2min → Edge cases: 30s. Total ~4min

What the Interviewer Tests

Your ability to explain substitutability beyond inheritance, understanding of behavioural contracts, and awareness of subtle pitfalls.

Common Follow-ups

  • What happens if a subtype strengthens preconditions? → It breaks substitutability because clients may pass inputs the subtype rejects.
  • Can covariant return types violate LSP? → Generally allowed if they preserve expected behavior, but must be used carefully.
💡 These follow-ups test your grasp of nuanced contract rules and practical implications.
🔍
Pattern Recognition

When to Use

When asked about SOLID principles, inheritance pitfalls, or designing robust class hierarchies.

Signature Phrases

'Explain the Liskov Substitution Principle''What happens when a subtype changes method behavior?''Compare inheritance vs LSP compliance'

NOT This Pattern When

Similar Problems

Practice

(1/5)
1. You need to create different types of vehicles (cars, bikes) that share a common interface, and sometimes you want to create entire families of related vehicles (e.g., electric car + electric bike) ensuring consistency. Which design pattern best fits this requirement?
easy
A. Builder Pattern, because it constructs complex objects step-by-step.
B. Abstract Factory Pattern, because it creates families of related objects ensuring consistency.
C. Factory Pattern, because it creates simple objects based on a type parameter.
D. Singleton Pattern, because it ensures only one instance of each vehicle type.

Solution

  1. Step 1: Understand the requirement for families of related objects

    The problem states the need to create related vehicles (e.g., electric car and electric bike) that belong to a family and must be consistent.
  2. Step 2: Match pattern to requirement

    Abstract Factory is designed to create families of related objects, ensuring that the created objects are compatible and consistent.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Abstract Factory creates related object families, Factory creates single objects [OK]
Hint: Families of related objects -> Abstract Factory [OK]
Common Mistakes:
  • Confusing Factory with Abstract Factory
  • Using Builder for simple object creation
2. Trace the sequence of method resolution when a subclass object calls an overridden method via a superclass reference variable. What happens step-by-step internally?
easy
A. The compiler binds the method call to the superclass method at compile time, and the superclass method executes at runtime
B. The compiler generates multiple versions of the method for each subclass, and the correct one is chosen at compile time
C. The compiler defers binding until runtime, where the object's actual class method is looked up via the vtable and executed
D. The method call is resolved by matching the method signature with the parameter types at runtime

Solution

  1. Step 1: Compile-time binding

    The compiler knows the reference type but defers binding for overridden methods to runtime.
  2. Step 2: Runtime dispatch

    At runtime, the actual object's class is identified, and the method pointer is retrieved from the vtable.
  3. Step 3: Method execution

    The overridden method in the subclass is executed, enabling dynamic polymorphism.
  4. Final Answer:

    Option C -> Option C
  5. Quick Check:

    Overriding uses dynamic dispatch via vtable lookup at runtime, not compile-time binding.
Hint: Overriding = runtime binding via vtable lookup
Common Mistakes:
  • Assuming compile-time binding for overridden methods
  • Confusing overloading resolution with overriding
  • Believing method signature matching happens at runtime
3. Which of the following statements about the Single Responsibility Principle is INCORRECT?
medium
A. SRP means a class should only have one method to ensure simplicity.
B. Applying SRP improves cohesion and reduces coupling.
C. A class should have only one reason to change, which means it should have only one responsibility.
D. Violating SRP can lead to fragile code that breaks when unrelated changes occur.

Solution

  1. Step 1: Analyze each statement

    A class should have only one reason to change, which means it should have only one responsibility. correctly states the core SRP definition.
  2. Step 2: Evaluate SRP means a class should only have one method to ensure simplicity.

    SRP is about reasons to change, not the number of methods; a class can have many methods if they serve one responsibility.
  3. Step 3: Confirm options A, B, and D

    Options A, B, and D are true: SRP improves cohesion, reduces coupling, and prevents fragile code.
  4. Final Answer:

    Option A -> Option A
  5. Quick Check:

    SRP ≠ one method per class; it's about one reason to change.
Hint: SRP is about reasons to change, not method count.
Common Mistakes:
  • Confusing responsibility with method count.
  • Assuming fewer methods always means better design.
  • Ignoring cohesion and coupling effects.
4. Suppose you want to implement a prototype pattern for an object that contains references to other objects which themselves may reference back to the original object (cyclic references). Which approach correctly handles deep copying in this scenario?
hard
A. Use a deep copy implementation with memoization to track already copied objects and avoid infinite recursion
B. Use a naive recursive deep copy without memoization, which will eventually copy all objects
C. Use shallow copy to avoid recursion issues, accepting shared nested references
D. Serialize the object to JSON and deserialize it, which naturally handles cyclic references

Solution

  1. Step 1: Understand cyclic references problem

    Naive recursion without tracking copied objects causes infinite recursion on cycles.
  2. Step 2: Evaluate solutions

    Memoization tracks already copied objects, preventing infinite loops and ensuring correct deep copy. Shallow copy shares references, breaking independence. JSON serialization cannot handle cycles and will fail.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Memoization prevents infinite recursion in cyclic graphs [OK]
Hint: Memoization is essential for deep copying cyclic object graphs [OK]
Common Mistakes:
  • Ignoring cycles causes infinite recursion or stack overflow
5. Suppose you want to extend the Template Method Pattern to allow clients to optionally skip multiple steps dynamically at runtime (not just condiments). Which modification best preserves the pattern's structure and flexibility?
hard
A. Override the entire template method in each subclass to conditionally skip steps as needed.
B. Add multiple hook methods in the base class for each optional step, with default implementations returning True or False.
C. Remove the base class and implement each beverage's recipe independently with duplicated code.
D. Use a flag parameter in prepare_recipe to decide which steps to execute, breaking encapsulation.

Solution

  1. Step 1: Understand requirement

    Need to optionally skip multiple steps dynamically while preserving fixed sequence and reuse.
  2. Step 2: Evaluate options

    Adding multiple hook methods in base class allows subclasses to override selectively without breaking skeleton.
  3. Step 3: Reject other options

    Overriding entire template method duplicates code and breaks pattern; flags break encapsulation; removing base class loses reuse.
  4. Final Answer:

    Option B -> Option B
  5. Quick Check:

    Multiple hooks preserve flexibility and structure [OK]
Hint: Use hooks for optional steps, not override template method [OK]
Common Mistakes:
  • Overriding template method to skip steps
  • Using flags breaking encapsulation