This is far from a silly example; it gets right to the core of the matter. As belorn mentioned, a square is a constrained rectangle, and inheritance by extension cannot represent this relationship.
> square is a constrained rectangle, and inheritance by extension cannot represent this relationship
A hypothetical nice type system, providing a push-out (path independent) lattice of theories/algebras (eg triples of types, operators, and laws) can represent this relationship by extension. It's just adding a law.
That we don't have such a type system available, is I suggest, perhaps the most crippling characteristic of our current tooling. But given the levels of type system research funding over the last decades, it's rather a self-inflicted injury. :/
Agreed, though I feel that phrasing it as 'adding a law' to include it under the umbrella of 'extension' tends to diminish, or distract from, the problem with inheritance as implemented in current mainstream languages. What you are describing seems to be a fundamentally different way of looking at the issue.
Fair. It seemed worth mentioning the larger context, and this seemed a plausible place.
Doing VR/AR, I've been struck by how not good the community is at attributing design constraints to cause. Constraints are simply echoed ("90 fps or sick!"), without attention to their context and scope of validity. Being unable to clearly see one's design space, impoverishes imagination, planning, and outcomes.
Many of the comments on this page reminded me of that. And parts of the OP. We can usefully discuss whether the apocryphal shoemaker had better today prohibit his oft-crippled children from dancing, or going outside, or walking, but it's worth bearing in mind that the root cause of the cripplings is the ongoing failure to provide shoes. And all the rusty bent nails we've left on the floor.
Inheritance can represent this relationship, as long as all the defined operations in the rectangle are covariant. Because squares are covariant (more constrained) than rectangles. This generally means that the rectangle type must be immutable.
Indeed, but unfortunately these complications almost never comes up when programming in current mainstream object-oriented languages is taught. Usually, the take-home lesson is, "if you have a type hierarchy, use inheritance - it's simple."
You are absolutely right that there is an education problem. I got lucky by randomly deciding to take the OOP principles elective. It's still not a required course at my school, though I know from recruiting trips that other schools include it.
I think there's a place for a language that separates inheritance from subtyping. A lot of misuse of inheritance that I see comes from inheriting for functionality instead of subtyping.