Basically when we designed a class, we use maintain Class hierarchies. We must
make sure that the new derived classes just extend without replacing the
functionality of old classes. Otherwise the new classes can produce undesired
effects when they are used in existing program modules.
LSP
states that if the module using any base class, then the reference to the Base
class can be replaced with a Derived class without affecting the functionality
of the program module.
Example : - A typical example that violates LSP is a Square class that derives
from a Rectangle class, assuming getter and setter methods exist for both width
and height. The Square class always assumes that the width is equal with the
height. If a Square object is used in a context where a Rectangle is expected,
unexpected behavior may occur because the dimensions of a Square cannot (or
rather should not) be modified independently. This problem cannot be easily
fixed: if we can modify the setter methods in the Square class so that they
preserve the Square invariant (i.e. keep the dimensions equal), then these
methods will weaken (violate) the postconditions for the Rectangle setters,
which state that dimensions can be modified independently. If Square and
Rectangle had only getter methods (i.e. they were immutable objects), then no
violation of LSP could occur.
public
class Rectangle
{
protected int _width;
protected int _height;
public int Width
{
get { return _width; }
}