Liskov Substitution Principle (LSP) in SOLID with Java Example

The Liskov Substitution Principle (LSP) is one of the five SOLID principles of object-oriented programming, formulated by Barbara Liskov. It states:

"Objects of a superclass should be replaceable with objects of its subclass without affecting the correctness of the program."

In simpler terms, if class B is a subclass of class A, then objects of class A should be replaceable with objects of class B without breaking the application.

Why is LSP Important?

LSP ensures that a derived class extends the behavior of a base class without altering its fundamental characteristics. Violating LSP can lead to unexpected behaviors, breaking polymorphism and making code more complex to maintain.


Example of LSP Violation

Incorrect Example (Violating LSP)

class Rectangle {
    protected int width;
    protected int height;

    public void setWidth(int width) {
        this.width = width;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public int getArea() {
        return width * height;
    }
}

class Square extends Rectangle {
    @Override
    public void setWidth(int width) {
        this.width = width;
        this.height = width; // Enforcing square behavior
    }

    @Override
    public void setHeight(int height) {
        this.width = height;
        this.height = height; // Enforcing square behavior
    }
}

public class LSPViolationExample {
    public static void main(String[] args) {
        Rectangle rect = new Square();  // Substituting subclass
        rect.setWidth(4);
        rect.setHeight(5);

        System.out.println("Expected Area: " + (4 * 5)); // Expecting 20
        System.out.println("Actual Area: " + rect.getArea()); // Output: 25 (Incorrect!)
    }
}

Why is LSP Violated Here?

  • The Square class breaks the behavior of Rectangle by forcing the width and height to be the same.
  • The program expects the area to be width * height = 4 * 5 = 20, but since Square modifies both dimensions, the actual area is 5 * 5 = 25, causing unexpected behavior.

Correct Example (Following LSP)

To fix this, we should avoid modifying inherited behaviors in a way that breaks expectations. A better approach is to use separate abstractions for Square and Rectangle.

abstract class Shape {
    public abstract int getArea();
}

class Rectangle extends Shape {
    protected int width;
    protected int height;

    public Rectangle(int width, int height) {
        this.width = width;
        this.height = height;
    }

    @Override
    public int getArea() {
        return width * height;
    }
}

class Square extends Shape {
    private int side;

    public Square(int side) {
        this.side = side;
    }

    @Override
    public int getArea() {
        return side * side;
    }
}

public class LSPExample {
    public static void main(String[] args) {
        Shape rect = new Rectangle(4, 5);
        Shape square = new Square(4);

        System.out.println("Rectangle Area: " + rect.getArea()); // 20
        System.out.println("Square Area: " + square.getArea()); // 16
    }
}

Why is This Correct?

  • The Shape abstract class defines a common contract (getArea()), but Rectangle and Square implement their own behaviors separately.
  • Rectangle and Square do not override each other’s behavior, ensuring LSP compliance.
  • Objects of Rectangle and Square can be used interchangeably without breaking expected behavior.

Key Takeaways

- Follow LSP by ensuring that subclasses do not break the expectations set by their base classes.
- Avoid overriding methods in a way that alters the base class's behavior incorrectly.
- Use separate abstractions when different behaviors are needed, instead of forcing a subclass to fit.
- Design classes such that a subclass can be substituted for its parent without causing unexpected behavior.

Thanks for reading! 🎉 I'd love to know what you think about the article. Did it resonate with you? 💭 Any suggestions for improvement? I’m always open to hearing your feedback so that I can improve my posts! 👇🚀. Happy coding! 💻

0 comments:

Post a Comment