Prefer Delegation to Inheritance

Benjamin Nortier at 21st Century Code Works has a great post exploring of the Liskov Substititution Principle in which he tries to determine if Square “is-a” Rectangle. He rightly concludes that a Square is not a Rectangle as far as development is concerned, whatever may be true in mathematics. (HT: Bob Koss)

I think the improper subclassing that Benjamin discusses usually stems from a commendable effort to reuse code, rather than abstract ontological considerations. Square and Rectangle share a lot of code, so it’s pretty tempting to extend Rectangle. A better way to do this is through delegation.

Let’s assume you have this class:

public class Rectangle {
  public void setWidth(int width) { this.width = width; }
  public void setHeight(int height) { this.height = height; }
  public int getArea(return width * height; }
  public int getPerimeter(return (width + height) * 2; }

Now you need to implement class Square, and it’s pretty tempting to simply extend Rectangle and change the definition of setWidth() and setHeight(). But there is a better way.

public class Square {
  private Rectangle r;
  public void setSide(int side) { r.setWidth(side); r.setHeight(side); }
  public int getArea() { return r.getArea(); }
  public int getPerimeter() { return r.getPerimeter(); }

This approach is superior because it does not violate the Liskov Substitution Principle, yet it still achieves about the same level of code reuse. But that reuse no longer comes at the cost of violating encapsulation.

Leave a Reply

Your email address will not be published. Required fields are marked *