🔥 Launch Offer: Interview Preparation Bundle @ ₹2,499 ₹9,999 • 75% OFF. Offer expires in 🔥 Launch Offer: Interview Preparation Bundle @ ₹2,499 ₹9,999 • 75% OFF. Offer expires in Interview Preparation Bundle @ ₹2,499 ₹9,999

00:00:00 Get Bundle
home java how-would-you-fix-an-lsp-violation
Interview guide Java 7 sections

How would you fix an LSP violation?

There isn't a single solution. The fix depends on the design. Common approaches are extracting behavior into an interface, redesigning the parent class, splitting the inheritance hierarchy, using…

Start reading
By javainterviewprep June 14, 2026 3 min read

There isn’t a single solution. The fix depends on the design. Common approaches are extracting behavior into an interface, redesigning the parent class, splitting the inheritance hierarchy, using composition instead of inheritance, or removing inheritance altogether. The key is that every subclass must honor the contract defined by the parent.

A Simple Rule to Remember

When designing inheritance, ask yourself:

“Can every child honestly do everything the parent promises?”

  • Yes → Inheritance is appropriate.
  • No → Rethink the design (interface, composition, hierarchy, or contract).

That’s the essence of the Liskov Substitution Principle.

There is no single fix for an LSP violation. The correct solution depends on why the inheritance exists and what the real-world domain looks like.

The important idea is:

If a child cannot fulfill the parent’s contract, then the inheritance hierarchy is wrong.

Let’s look at different ways to solve the Bird and Penguin example.


Solution 1 (Most Common) – Move the behavior to a separate interface ✅

Not every bird can fly.

So don’t put fly() inside Bird.

class Bird {
public void eat() {
System.out.println("Bird is eating");
}
}

Create a separate interface.

interface Flyable {
void fly();
}

Flying birds:

class Sparrow extends Bird implements Flyable {

@Override
public void fly() {
System.out.println("Sparrow is flying");
}
}

Penguin:

class Penguin extends Bird {
}

Now,

Flyable bird = new Sparrow();
bird.fly();

No problem.

This is considered the best solution because the design now models reality correctly.


Solution 2 – Split the hierarchy

Instead of

Bird
↑
Penguin

Create two parent classes.

Bird
↑
FlyingBird
↑
Sparrow

Bird
↑
NonFlyingBird
↑
Penguin

Example

class Bird {
}
class FlyingBird extends Bird {

public void fly() {
System.out.println("Flying");
}
}
class Penguin extends Bird {
}

Now Penguin never inherits fly().


Solution 3 – Use Composition Instead of Inheritance

Sometimes inheritance is the wrong choice.

Instead of

Penguin extends Bird

Use

Penguin HAS-A Bird

Example

class Bird {
public void eat() {
System.out.println("Eating");
}
}
class Penguin {

private Bird bird = new Bird();

public void swim() {
System.out.println("Swimming");
}

public void eat() {
bird.eat();
}
}

No incorrect inheritance.


Solution 4 – Redesign the Parent Contract

Sometimes the parent itself is poorly designed.

Instead of

class Bird {

public void fly() {
}
}

Make it

abstract class Bird {

public abstract void move();
}

Now

class Sparrow extends Bird {

@Override
public void move() {
System.out.println("Flying");
}
}
class Penguin extends Bird {

@Override
public void move() {
System.out.println("Walking and Swimming");
}
}

Every bird moves.

No violation.


Solution 5 – Remove the Inheritance

Sometimes the classes simply aren’t in an “is-a” relationship for the behavior you’ve modeled.

Bird
Penguin
Sparrow

No inheritance at all.

This is less common but sometimes correct.


Which Solution Should You Choose?

SituationBest Solution
Only some subclasses have a behavior (e.g., fly)✅ Extract an interface (Flyable)
Parent class is designed incorrectly✅ Redesign the parent contract
Inheritance doesn’t represent reality✅ Use composition instead of inheritance
Need separate categories✅ Split the hierarchy
Inheritance adds no value✅ Remove inheritance