Inheritance is a local maxima. When the hierarchy of classes to consider is small, it often “seems to fit”. It allows the programmer to progress quickly and with low effort as a lot of the code sharing behavior is provided by the inheritance mechanism.
Trouble often comes down the line. We keep adding classes, and soon we find that the hierarchy no longer is “shaped like a tree”. A soccer ball is a spherical object but also a sports equipment and a bouncing object, and there’s no way to organize those into branches.
Our reality isn’t “tree-like”, except when we simplify it extensively.
That’s true of all knowledge organizational structures though. Even with composition, you end up with hierarchies that later you might turn on their heads, and also, those structures might end up being cyclical.
Paradigm shifts happen and shake up even loosely organized into structures like human perception, and most people’s perceptions aren’t trees
Trouble often comes down the line. We keep adding classes, and soon we find that the hierarchy no longer is “shaped like a tree”. A soccer ball is a spherical object but also a sports equipment and a bouncing object, and there’s no way to organize those into branches.
Our reality isn’t “tree-like”, except when we simplify it extensively.