I am new to design and learning the design principles.
It says deriving square from rectangle is a classic example of violation of Liskov's Substitution Principle.
If that's the case, what should be the correct design?
I believe the reasoning is something like this:
Let's say you have a method that accepts a rectangle and adjusts its width:
public void SetWidth(Rectangle rect, int width)
{
rect.Width = width;
}
It should be perfectly reasonable, given what a rectangle is, to assume that this test would pass:
Rectangle rect = new Rectangle(50, 20); // width, height
SetWidth(rect, 100);
Assert.AreEqual(20, rect.Height);
... because changing a rectangle's width does not affect its height.
However, let's say you've derived a new Square class from Rectangle. By definition, a square has height and width always equal. Let's try that test again:
Rectangle rect = new Square(20); // both width and height
SetWidth(rect, 100);
Assert.AreEqual(20, rect.Height);
That test will fail, because setting a square's width to 100 will also change its height.
Thus, Liskov's substitution principle is violated by deriving Square from Rectangle.
The "is-a" rule makes sense in the "real world" (a square is definitely a kind of rectangle), but not always in the world of software design.
Edit
To answer your question, the correct design should probably be that both Rectangle and Square derive from a common "Polygon" or "Shape" class, which does not enforce any rules regarding width or height.