You reduced the "Square" class to a convenient implementation helper.
Whatever type they choose to use, clients of your class hierarchy now only see one interface: getWidth/getHeight.
And they can't make assumptions based on the type they see, as both "Square" and "Rectangle" might have "getWidth()!=getHeight()".
So they must handle the generic "rectangular" case.
So, for the client, there's absolutely no visible difference between a "Square" or a "Rectangle". Which means there's no point in dealing with two classes anymore : all client code will then take "Square" objects, and deal with them as geometrical rectangles.
Whatever type they choose to use, clients of your class hierarchy now only see one interface: getWidth/getHeight. And they can't make assumptions based on the type they see, as both "Square" and "Rectangle" might have "getWidth()!=getHeight()". So they must handle the generic "rectangular" case.
So, for the client, there's absolutely no visible difference between a "Square" or a "Rectangle". Which means there's no point in dealing with two classes anymore : all client code will then take "Square" objects, and deal with them as geometrical rectangles.