Rex Kerr
1 min readJan 20, 2025

--

This doesn't really solve the problem, though, because you can have

public Rectangle scale(double factor) { return new Rectangle(this.width * factor, this.height * factor) }

and Square will inherit it but in this case the return value is still a square! So you still need to override it, if you want your Square to be functional:

override public Square scale(double factor) { return new Square(this.size * factor) }

But it's Square, not Rectangle, that appears to have the superinterface where scale is well-defined. This makes code reuse a real pain: supposedly Rectangle is the superclass, but Square acts more like it is in this case.

You could try having, in abstract class Shape,

public Shape scale(double factor);

but now you don't keep the specific shape type, even though the whole point of scaling is that you always can keep the specific shape type.

Languages with more advanced type systems than Java (e.g. Scala) can do somewhat better. But fundamentally this sort of changed contract is why OOP is less universally helpful than was hoped at the height of buzz about OOP. Switching to immutable objects helps with some problems but makes others worse (mostly losing the specific type).

--

--

Rex Kerr
Rex Kerr

Written by Rex Kerr

One who rejoices when everything is made as simple as possible, but no simpler. Sayer of things that may be wrong, but not so bad that they're not even wrong.

Responses (1)