2

I had a simple concept for a 2d game. Think of like a Final Fantasy / D&D setting. I was working in C# but it's more of a general single-inheritance OO issue. I'm just assuming there's a scheme where you can implement many interfaces but inherit only one class.

There are three types of entities in the game: players, villagers, and enemies. To clarify, there can be multiple players (AI) because some may join the party.

For actions: Players can do combat and dialogue. Villagers can only use dialogue. Enemies can only do combat.

For state: All entities have a position on the map. Combatants always have current health, max health, etc. Dialogue entities always have some specific greeting text, dialogue options, etc.

Player, Villager, and Enemy would be my concrete classes. It seems I want 2 interfaces: Combat and Dialogue, handling all the actions. So far so good - however, these entities share state in a way problematic for single inheritance. Based on my design, it seems I want

  • an abstract Entity class with a position on the map
  • abstract classes AbstractCombatant the other AbstractDialogue both inheriting from Entity. AbstractCombatant, for example, has the state for health, equipment, etc.

The problem here is that Player would want to inherit from both Combatant and Dialogue abstract classes. With single inheritance, I can't. And if I could, I would have the diamond inheritance problem from the Entity class. Even if I just had my concrete classes inherit Entity instead, that would be another multiple inheritance problem. And of course, if I totally took the Entity part out of the equation and just mapped entities to positions separately, I would still suffer from the problem with Player inheriting from two classes.

I couldn't come up with a single-inheritance design that doesn't duplicate implementation. What is the best way to set up a class/interface hierarchy for this scenario?

helb
  • 7,609
  • 8
  • 36
  • 58
  • 1
    how about composition, mixins rather than inheritance – Scorpion Feb 12 '15 at 10:32
  • Sounds to me like AbstractCombatant and AbstractDialogue should be interfaces. Then your concrete classes would inherit from Entity and implement the interfaces they need. – Emil Laine Feb 12 '15 at 10:37
  • 1
    Agreed with ^ (2 comments above). Do you always want your enemies to never have dialogue options? Seems to me like if you wanted to put a boss in the game sometime in the future this would then change? – camdixon Feb 12 '15 at 10:38
  • ^ Adding to the above: You could then make an additional concrete Boss class that would inherit from Enemy and add AbstractDialogue on top of that. Maybe. – Emil Laine Feb 12 '15 at 10:40
  • possible duplicate of [Need multiple inheritance functionality in C#. What am I doing wrong?](http://stackoverflow.com/questions/6430275/need-multiple-inheritance-functionality-in-c-what-am-i-doing-wrong) – helb Feb 12 '15 at 12:17
  • zenith: By making those classes interfaces you will need to implement every single method at least twice (once for each class that needs it) which is exactly what you don't want if the different classes should behave identically. This is why the solution suggested by `helb` is commonly used. – H W Feb 12 '15 at 12:55
  • @zenith Also, my design currently has interfaces for those things but also the abstract classes implementing those interfaces to share state. –  Feb 12 '15 at 19:06
  • @camdixon good point - I may be too restrictive with this design. And thanks everyone else for the suggestions. –  Feb 12 '15 at 19:08

1 Answers1

3

It is only natural that you want to have a class for each concept (player, enemy, villager, etc.) in your problem domain / business domain. The issue arises naturally when these concepts share common features. Consider this example:

class House : IHouse
{
    public int StreetNumber { get; }
}

class Boat : IBoat
{
    public double SpeedKnots { get; }
}

class HouseBoat : House, Boat  // does not compile
{
}

The simplest way to get around this is using aggregation.

Balanced

Keep references to all underlying concepts and implement the appropriate interfaces to provide all the required functionality.

class HouseBoat : IHouse, IBoat // implementing both interfaces is ok
{
    private House house;
    private Boat boat;

    int IHouse.StreetNumber { get { return this.house.StreetNumber; } }
    double IBoat.SpeedKnots { get { return this.boat.SpeedKnots; } }
}

Biased

Derive from one of the concepts (the one which is more similar) and implement the interface for the other concept(s).

class HouseBoat : Boat, IHouse // is more like a Boat
{
    private House house; // model for the house aspects

    int IHouse.StreetNumber { get { return this.house.StreetNumber; } }
}

Further Reading

This is quite a common problem since it comes naturally as mentioned above and both Java and C# do not allow multiple inheritance. A simple google query with the right search terms will provide abundant material.

helb
  • 7,609
  • 8
  • 36
  • 58
  • Good example. I've done some searching for this problem (without finding really satisfying solutions), and I believe I've read about this pattern in Effective Java. I understand the benefit of composition over inheritance, but honestly this pattern seems hacky, with a large amount of boilerplate code as the interfaces and number of concrete classes grow. But perhaps there is no really elegant solution even in my specific case. I was hoping I could restructure this hierarchy without multiple inheritance or aggregation, but it sounds like your solution is still the best workaround. Thanks. –  Feb 12 '15 at 19:30