Last week, while working on some the heroes, we ran into an almost a textbook example of the use of inheritance and we thought of sharing it. If you are programmer this will post will most likely be too basic, but perhaps you are just taking your fist steps at coding, or it is something you just dabble a bit in. In that case this may be useful, and also it is a chance to show you a bit of the game’s code and structure.
It all started with Orpheus. Quite a while ago we decided to add Orpheus as one of the heroes in the game, and that giving a boost the units nearby (the units that were close enough to hear him sing) would be a suitable ability for him. And so we did. Roque drew him, animated him, we added some code and voilà. Orpheus was in the mob, all was right with the world. However, some time later we thought about adding more musicians to the mob, and giving them the same ability as Orpheus. It seemed like a good idea, half the work was already done and it made sense that musicians would have similar abilities, so we created Elviros. You can see below a bit of the code for them.
Unsurprisingly, since they both do pretty much the same, the only difference in the code were a couple of values (Orpheus is better at what he does, sorry Elviros). Not only this, our plan was to add a few other musicians as well, so we were probably going to have to copy that code a few more times too. Here is when inheritance comes to the rescue. We created a new class called HeroMusician, which contained all the code for the special abilities, and made Elviros and Orpheus inherit from that class.
Now if we have to make any changes the musicians abilities we only have to change the code in the HeroMusician class instead of doing it throughout several classes. And Orpheus and Elviros’ code is now much smaller, pretty much nothing but setting their stats and modifiers. The magic of inheritance.
The real trick while dealing with inheritance, however, is not learning how to use it, but learning how not to overuse it. Your code can soon become flooded with tons of classes that do almost nothing but look neat in a hierarchy tree. It is very tempting to start adding classes because it makes sense object-wise, to scrape a couple of lines of code from some method, or because you may need them in the future, but you should think carefully before doing so. Having a thousands little classes can make your code as unreadable as having classes with thousands of lines of code.
This is why our policy has from day one adding classes only when needed, like in the example above. And based on that philosophy that we ended up with our current class hierarchy:
You can see the new class HeroMusician in the lower level, which means that Orpheus and Elviros not only inherit from Hero Musician but also from Hero, Unit and Destroyable. Is this the best way to do it? I can’t tell for sure. The hierarchy may change in the future, but we will try to keep on working with the same strategy, without abusing the wondrous inheritance.
Edit: There have been some very interesting and accurate comments on reddit, mostly about the subject of composition vs inheritance, which point out a couple of things that are worth mentioning here as well. Several people pointed out that the problem of the musician heroes could have been solved using composition, for example making the musicians ability a component and adding that component to the appropriate heroes. It’s true. I never mention composition in the post but as is it also pointed out in the comments, favoring composition over inheritance is a more scalable approach, and can be an effective method to avoid ending up with a cluttered class hierarchy.
-
Munitis
-
Sebastián Gioseffi
-