Skip to main content

Command Palette

Search for a command to run...

LSP Isn’t Theory—It’s How You Stop Inheritance Bugs in Interviews

Updated
3 min read
LSP Isn’t Theory—It’s How You Stop Inheritance Bugs in Interviews
B

bugfree.ai is an advanced AI-powered platform designed to help software engineers master system design and behavioral interviews. Whether you’re preparing for your first interview or aiming to elevate your skills, bugfree.ai provides a robust toolkit tailored to your needs. Key Features:

150+ system design questions: Master challenges across all difficulty levels and problem types, including 30+ object-oriented design and 20+ machine learning design problems. Targeted practice: Sharpen your skills with focused exercises tailored to real-world interview scenarios. In-depth feedback: Get instant, detailed evaluations to refine your approach and level up your solutions. Expert guidance: Dive deep into walkthroughs of all system design solutions like design Twitter, TinyURL, and task schedulers. Learning materials: Access comprehensive guides, cheat sheets, and tutorials to deepen your understanding of system design concepts, from beginner to advanced. AI-powered mock interview: Practice in a realistic interview setting with AI-driven feedback to identify your strengths and areas for improvement.

bugfree.ai goes beyond traditional interview prep tools by combining a vast question library, detailed feedback, and interactive AI simulations. It’s the perfect platform to build confidence, hone your skills, and stand out in today’s competitive job market. Suitable for:

New graduates looking to crack their first system design interview. Experienced engineers seeking advanced practice and fine-tuning of skills. Career changers transitioning into technical roles with a need for structured learning and preparation.

LSP Isn’t Theory—It’s How You Stop Inheritance Bugs in Interviews

Liskov Substitution Principle diagram

The Liskov Substitution Principle (LSP) is simple and practical: if S is a subtype of T, you must be able to use S anywhere T is expected without breaking correctness. In interviews, this is less academic rule and more of a bug-catching litmus test for inheritance design.

The classic trap: Square inherits Rectangle

It often "looks" right to model a Square as a special Rectangle. But the trouble starts when the parent exposes mutation operations like setWidth and setHeight.

Example (Java-like pseudocode):

class Rectangle {
  int width, height;
  void setWidth(int w) { width = w; }
  void setHeight(int h) { height = h; }
  int area() { return width * height; }
}

class Square extends Rectangle {
  void setWidth(int w) { width = w; height = w; }
  void setHeight(int h) { width = h; height = h; }
}

// Client code expecting a Rectangle:
Rectangle r = new Square();
r.setWidth(5);
r.setHeight(4);
// Expected area: 20, actual area: 16 — substitution broke correctness

Why it fails: a Rectangle allows width and height to vary independently. A Square enforces an invariant (width == height). When a client relies on Rectangle's contract (independent setters), substituting a Square violates that contract.

How to use LSP in interviews (quick checklist)

  • Ask about the parent type's public contract: which operations and invariants does it expose?
  • Ask whether instances are mutable or immutable. Mutable setters often reveal substitution problems.
  • Check for strengthened preconditions or weakened postconditions in the subclass — both are red flags.
  • If a proposed subclass cannot honor all behaviors the parent promises, it shouldn’t extend the parent.

When explaining your decision in an interview, say explicitly: "If this subclass can't maintain the parent's contract for every client, I'd avoid inheritance and choose composition or a different abstraction." That shows both theory and practical judgment.

Safer alternatives

  • Composition: give Square a Rectangle internally or store side length directly. Expose only the behaviors you can guarantee.
  • Interface segregation: separate immutable/querying behavior (e.g., area(), perimeter()) from mutating behavior (e.g., setWidth()).
  • Factory methods or distinct types: provide distinct constructors or builders for shapes that don't share a mutating contract.
  • Design by contract / tests: write tests that validate substitution (e.g., pass instances of the subtype to existing client tests for the parent).

Example: prefer composition over inheritance

class Square {
  private final int side;
  Square(int side) { this.side = side; }
  int area() { return side * side; }
}

// or
class RectangleLike {
  private int width, height;
  // only expose operations you can honestly support
}

Final tip for interviewers and candidates

Treat LSP as a practical question: when asked to extend or refactor types, explicitly reason about the parent contract and client expectations. If substitution would change observable behavior, choose composition or redesign the abstraction. That reasoning—clear, testable, and tied to correctness—is what interviewers want to hear.

#SOLID #SoftwareEngineering #SystemDesign

More from this blog

B

bugfree.ai

394 posts

bugfree.ai is an advanced AI-powered platform designed to help software engineers and data scientist to master system design and behavioral and data interviews.