Yes, the problem is that mutable and immutable objects have different methods and therefore fit into different inheritance trees.
If you construct an immutable rectangle and pass in the same width and height, you have a square. (An object implementing the same API could be implemented by a subclass whose constructor just takes a width.)
If you construct a mutable rectangle with the same width and height, you have a rectangle whose shape is temporarily square until a setter is called. The "square" invariant doesn't hold for the object's entire lifetime, so it's not a square. Instead you could write an isSquare method and sometimes it would return true, depending on the object's state.
The inheritance relationships you expect from thinking about math only hold for immutable objects.
I actually don't think the problem is one of mutability/immutability – it's just that a mutable setting very clearly exposes the problem.
I think the core of the problem is that the object model has permanently and irreversibly associated an identity to an object based on attributes that are actually malleable. Someone else made a good connection to pastry dough, which can be shaped even more freely. We would never hold up a clump of pastry dough, however it is shaped, and proclaim "Down at the core, this is fundamentally a rectangle," because we know the rectangleness is just a temporary description of its spatial attributes, which may change the very instant we accidentally drop the dough and it hits the floor.
Similarly, if "being a rectangle" in our model means "being able to change the width and height independently", then the square should never have been allowed to be a subtype of the rectangle.
I guess this touches more and more closely on what the submitted article discusses, and my initial confusion stemmed from the fact that I have never before heard the "can change width and height independenly" definition of a rectangle, because from my maths background a rectangle is just a description something that happens to be, not something that changes itself.
Yes, and that's directly related to immutability. Immutable objects are timeless; their initial state is their final state. Any property that holds for their initial state can be encoded in the type and placed somewhere above it in the inheritance hierarchy.
You can think of a mutable object as a collection of immutable and mutable properties, where only the former can be moved into the type and become part of the type hierarchy.
This distinction isn't really about inheritance; it's more about what a type is in the presence of mutability. The type represents the invariants.
If you construct an immutable rectangle and pass in the same width and height, you have a square. (An object implementing the same API could be implemented by a subclass whose constructor just takes a width.)
If you construct a mutable rectangle with the same width and height, you have a rectangle whose shape is temporarily square until a setter is called. The "square" invariant doesn't hold for the object's entire lifetime, so it's not a square. Instead you could write an isSquare method and sometimes it would return true, depending on the object's state.
The inheritance relationships you expect from thinking about math only hold for immutable objects.