I'm looking for some "Best Practices" -type explanations here.
This specific example applies to games (because this is Gamedev, derr) but really speaks to any instance of multiple inheritance being deployed across a class architecture.
Let's take an RPG. You have many items, monsters, NPCs, .... many. All of these are obviously represented as objects. So let's say we have classes Item and Monster (and like 20 more):
class Item
{
int value;
double whatever;
// ...
}
class Monster
{
int hp;
int thaco;
int ac;
// ...
}
Now I would like to introduce the concept of Magic. *Anything* and everything that is "magical" has several data fields and methods, namely:
int mp;
int maxMP;
LinkedList<Spell> spells;
bool cast(Spell*)
...
Managed languages such as Java and C# prohibit multiple inheritance, referencing "increased complexity" and the "diamond problem" as reasons for doing away with it. Other languages such as C++ allow it.
I see a number of avenues possible here (and the avenue I choose of course is language-dependen). However I would like to hear what anybody has to say about these proposed alternatives (and of course whatever you can contribute as well).
(1) Pure Multiple Inheritance.
class Item : GameObj, Magic
Items are thus extensions of type GameObj and the Magic class.
(2) Magic Interface
interface IMagic { bool cast(Spell*); /* etc... */ }
This enforces a contract for every implementing class, so we might override for magic items and magic monsters separately, maybe like this:
class Monster : Magic
{
int hp;
int thaco;
int ac;
bool cast(Spell* splz)
{
// whatever
}
}
However there are now two problems: (1) we don't enforce mp and maxMP data fields in any magic objects, and (2) we now require every monster to be magical, which we don't want, because as we all know, not every monster is magical.
(3) Virtual Methods
We could make GameObj magical and give it virtual functions:
class GameObj
{
// ... whatever
public virtual bool cast(Spell*);
}
And now we can choose to override it in certain classes, or not in others. Thus we could have an Item class which inherits GameObj and does not override (for non magical items) and a MagicItems class which also inherits GameObj and does override (for magic items). The problems here are numerous : Item and MagicItem are different types which make them incompatible for collections and other mechanism (whereas they should be viewed as the same, essentially). Also its getting complex and wreaks of spaghetti.
So basically, from a Best Practices, standpoint, what is the best choice to run with here (pay no attention to language choice, I'm really looking for good engineering advice)? And why?