Circle-Ellipse Problem
en.wikipedia.org
en.wikipedia.org
That example may look impractical. Here's a better one: define SanitizedString as a subclass of String (if your language allows that). Methods that output HTML to the client can take SanitizedStrings as input, so the type checker ensures the absence of XSS attacks. The constructor of SanitizedString could take an ordinary String and sanitize it, and that's the whole implementation of SanitizedString, because all other methods are already provided by String and none of them can break the sanitization because String is immutable. So using immutable objects allows you to write less code and get more compile-time guarantees.
string.convertToHTML() would escape special characters as HTML entities, preserving the fact that it's just a benign text.
In the ass-backwards mutable-OO world, a rectangle "is-a" square, because it can be a square. Under the same requirements (x==y), a rectangle is a square. Any action which acts on a square will do precisely the same thing with a square rectangle which inherits from a square.
Similarly, a get-bounding-box for a rectangle inheriting from a square must always return a square box - a get-bounding-rectangle method must be created to handle the new, non-square output.
Rectangles supercede squares in every way, therefore a rectangle is-a square, and it is more. The mathematical "is-a" is essentially the reverse of this - a square is a rectangle with restrictions.
Perhaps, as you suggest, this is a function that should be external to the instances. But I repeat myself:
http://weblog.raganwald.com/2007/10/too-much-of-good-thing-n...
What's broken is relying solely upon this mechanism to express all relationships. When your only relations are "Has" and "Is", even English would be hard pressed to express things elegantly.
"X is Y" in English (and math) seems to have different implications than "X IS-A Y" does in statically typed, class-based OOP.
As for asking for expressing math, things like CL's generic methods or Haskell's typeclasses model this sort of ad hoc series of relationships much more elegantly, in my opinion.
I think this is why everyone was saying "reuse failed" back in the late 90's and why projects, like IBM's, to produce standard business object models failed. Shortly afterwards, folks like Ralph Johnson were saying stuff along the lines of how software reuse wasn't a failure, that it worked well, but it only worked in the small context of specific projects or applications.
First thought: don't provide scaling methods - that's an operation best left to non-method functions or procedures. We scale lots of shapes in lots of ways that can make their original names less applicable.
After that, I started considering the models and their respective inheritance. If we expect the programming organizational structure to match the geometric organizational structure (e.g. circles are ellipses with the same axial lengths), then we might be thinking about the problem the wrong way. Do we model the hierarchy on the Real World or in a way that makes more sense in our library? I suppose it depends entirely on our purposes.
Sure, a circle's requirements for state are less than an ellipse, but it won't hurt to just draw a circle based on that additional state. Even the circumference and area formulas work out fine. So why, if I'm not coding for an resource-limited environment, am I creating a circle class anyway? They're all elipses anyway.