| This is a strong argument against inheritance, but that isn't everything about OOP. Just one well supported advanced abstraction (That I would also argue should be rarely used.) I would argue that just having strong type system and bundling methods with data gets you the vast majority of the usefulness of OOP. Liskov, Open/Closed, Message Passing, and other theoretical abstractions be damned. EDIT - Where are the good places to use inheritance? There are only a few I can think. One is when you are trying to create a system that inverts dependencies by allowing a plugin system or follows some sort of nuanced workflow that others might want to "hook into". But that isn't the only way to do that, maybe other ways would be better like passing in functors. Another situation I have seen recently is when creating a kind of data or messages that differ only by type and maybe a few small pieces of behavior and they are all known up front. |
Yes, a module system brings almost all of the advantages of OOP. The one remaining is structure abstraction (things like interfaces on Java derived languages, or type classes on Haskell derived ones).
But well, none of those are even typically associated with OOP. The OOP languages just have those features, like they have variables too.