Hacker News new | past | comments | ask | show | jobs | submit login

I feel as though the rectangle/square example falls down mostly because of a linguistic trick.

Rect->Square could be a perfectly reasonable type hierarchy, as long as you don't allow self-mutation of the very attribute that defines this specialization. But then, mutation tends to wreak havoc on inheritance anyway (e.g., covariance/contravariance) -- and almost everything else. When I take the needle out of my record player, it can't play records any more, so is it really still a "record player"?

This isn't special to any particular type of inheritance, either. If you let all the air out of your ball, it's no longer a sphere, so even with purely ontological types, you're already in trouble. Inheritance isn't the problem. Mutation is.




This would be overengineering, but the following six types would solve the problem:

* ImmutableSquare

* ImmutableRectangle

* MutableSquare

* MutableRectangle

* Square

* Rectangle

The "Mutable..." classes are mutable, the "Immutable..." classes are immutable, and the "Square" and "Rectangle" classes mean that you can read the values, but there is no guarantee about either mutability or immutability.

In this system, "ImmutableSquare" and "MutableSquare" are subtypes of "Square"; "ImmutableRectangle" and "MutableRectangle" are subtypes of "Rectangle"; and also "ImmutableSquare" is a subtype of "ImmutableRectangle" (and therefore "Rectangle").

But if you go this way, don't be surprised when you end up with millions of classes.


In some languages, there are also (non/)threadsafe variants of mutable classes. As you say, this approach blows up quickly.

If I saw that, I would ask what 'problem' it's trying to solve. Is mutation actually the goal, or simply the means? In languages which don't support general mutation (I'm writing Clojure right now), I really don't miss it at all.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: