I admit, I have made the sin of overusing, and even abusing inheritance. The first (text) game project that I made when I was taking my OOP course went as far as "Locked door" and "unlocked door" from "Door" and "Room with one door", "Room with two doors", and so on from "Room".
With the (graphical) game I worked on recently, I thought I had learned my lesson and put a limit on using inheritance. However I noticed the problems soon beginning to appear. My root class was beginning to bloat more and more, and my leaf classes were full of duplicate codes.
I thought I was still doing things wrong, and after looking it up online I discovered that I wasn't the only one with this problem. It's how I ended up discovering Entity systems after some thorough research (read: googlefu)
When I began reading on it, I was able to see how clearly it was able to solve the problems I was having with the traditional OOP hierarchy with components. These were in the first readings however. When I stumbled upon more… “radical” ES approaches, such as the one at T-machine.
I began disagreeing with the methods they were using. A pure component system seemed either overkill, or rather, unintuitive, which is probably the strength of OOP. The author goes so far as to say that ES system is the opposite of OOP, and while it may be usable along OOP, it really shouldn’t. I'm not saying it's wrong, but I just didn't feel like a solution I would like to implement.
So to me, and to solve the problems I was having at the beginning of the post, without going against my intuitions, is to still use a hierarchy, however it won’t be a monolithic hierarchy like the ones I used before, but rather a polylithic one (I couldn’t find a word opposite to monolithic), which consists of several, smaller trees.
The following example shows what I mean (this is inspired by an example I found in Game Engine Architecture, Chapter 14).
I would have a small tree for vehicles. The root vehicle class would have a rendering component, a collision component, position component etc..
Then a tank, a subclass of vehicle would inherit those components from it, and be given it's own "cannon" component.
The same goes for the Characters. A character would have it's own components, then the Player Class would inherit it, and be given an Input controller, while other enemy classes would inherit from the Character class and be given an AI controller.
I don't really see any problems with this design. Despite not using a pure Entity Controller System, the problem with the bubbling up effect, and the large root class is solved by using a multi-tree hierarchy, and the problem of the heavy, code duplicating leafs is gone since the leafs don't have any code to begin with, just components. If a change needs to be done to the leaf level, then it's as simple as changing a single component, instead of copy pasting the code everywhere.
Of course, being as inexperienced as I am, I did not see any problems when I first started using the single hierarchy, inheritance heavy model, so if there are problems with the model that I'm currently thinking of implementing, I wouldn't be able to see it.
P.S: I am using Java, so using multiple inheritance to implement this instead of using normal components is not possible.
P.P.S: Intercomponent communications will be done by linking dependent components to each other. This will lead to coupling, but I think it's an ok trade off.