1 - "There are actually several problems here. Thread safety is one, but let’s assume the class doesn’t need to be thread-safe."
The Rectangle implementation has a thread issue without regard to the Square subclass:
public double getPerimeter() {
return 2*width + 2*height;
}
2 - "In object oriented programming, it is necessary that a subclass be able to fulfill the contract of its superclass. In this case, that means the square has to respond to setHeight() and setWidth() calls. However doing so enables the square to violate the nature of a square. A square cannot stand in for a rectangle.You can try to work around this by overriding the setHeight() and setWidth() methods. For example, one might call the other:...
However this is fundamentally unsatisfying because there is no reasonable expectation that calling one of setHeight() on a Rectangle object will also invoke the setWidth() method or vice versa."
This is where things unwind. It is perfectly expected that calling setHeight() on a Square will also change its width.
3 - "We could instead just forbid setHeight() and setWidth() completely by throwing UnsupportedOperationException"
Yep, you could do that and it does show you are doing more work in working around using Square as a subclass of Rectangle. So either don't subclass it or accept the fact that its perfectly normal that if you have a Square, changing either its width or height will effect the other.
The author is trying too hard here. Its decent writing and a good attempt to show how subclassing can lead to unintended consequences. But this is not a great example.