
Is a Square a Rectangle?
In Geometry, a square is a special case of rectangle where the height and width of the shape are equal. When modelling squares and rectangles in object-oriented programming languages, defining this relationship can lead to unexpected bugs.
The "IS A" Relationship
The relationship between a subclass and its base class is often called an "IS A" relationship because the subclass is a version of the superclass. For example, you may develop an application that holds details of team members within an organisation. You may create a TeamMember class that is the base type for the SoftwareDeveloper class. As you can substitute SoftwareDeveloper objects where a TeamMember is expected, you can say that a SoftwareDeveloper is a TeamMember.
The concept of the "IS A" relationship can be misleading. When determining if one type should inherit from another, it is important to remember that you are dealing with representations of real-world objects and not the objects themselves. In the above relationship, a physical programmer is a physical team member. The behaviour of a programmer object is also an extension of the behaviour of a team member. An inheritance relationship is therefore suitable. There are many situations where the relationship between two physical objects suits an "IS A" relationship but where their behaviours do not.
Squares and Rectangles
One of the situations where the relationship between physical objects and their representations differs is the relationship between squares and rectangles. Geometrically, a square is a rectangle. Both meet the requirements of a rectangle; they are four-sided shapes where all corners are right-angles. Squares have an additional property that all sides are the same length.
The physical "IS A" relationship between a square and a rectangle may lead you to develop a class hierarchy where Square is a subclass of Rectangle. You may reason that the physical relationship can be mapped directly to an inheritance relationship in code. This is not the case because of some subtle but significant problems relating to the SOLID principles, most notably the Liskov Substitution Principle.
We can demonstrate the flawed inheritance relationship by creating Rectangle and Square classes in C# and seeing where problems arise. The example code will be simplistic to show that problems start to occur quickly. They would worsen as further functionality was added. To begin, create the Rectangle class with properties for Height and Width and a method to calculate the shape's area:
class Rectangle
{
public virtual int Height { get; set; }
public virtual int Width { get; set; }
public int CalculateArea()
{
return Height * Width;
}
}
Next create the Square class, using Rectangle as its base type:
class Square : Rectangle
{
}
The above Square type is not ideal as it allows squares to be defined without a matching height and width. Currently Square is nothing more than a Rectangle with a new name. One way to update the class, to ensure that represented objects are indeed square, is to override the property setters. When one dimension is set, the other could be updated to match. The revised code is shown below:
class Square : Rectangle
{
public override int Height
{
get { return base.Height; }
set { base.Height = base.Width = value; }
}
public override int Width
{
get { return base.Height; }
set { base.Height = base.Width = value; }
}
}
15 January 2011