0

I have a class called BagItem and another class called EquipmentItem both classes are exact the same in methods, etc, with the exception of 1 property.

BagItem have:

public InventoryBagType BagType { get; private set; }

EquipmentItem have:

public InventoryEquipmentType EquipmentType { get; private set; }

I guess I should mention, BagItem refer to items that are in the character's bag while EquipmentItem I should have probably named it EquippedItem which refer to item currently equipped by the character.

From those 2 classes I have other classes that inherit from one or another.

Then from EquipmentItem for example I have CombatEquipmentItem which inherits from EquipmentItem and CombatEquipmentItem only have one extra property.

public CombatEquipmentType SlotType { get; private set; }

At this point I don't know if CombatEquipmentItem will have or not more properties or methods, neither if either BagItem or EquipmentItem will either.

I was considering creating yet another class InventoryItem that would keep all the common entries from BagItem and EquipmentItem and they would inherit from it and by its turn CombatEquipmentItem from it.

Should I eliminate BagItem and EquipmentItem for InventoryItem and keep both the properties there and either set one or another as null based on the item and inherit anything else from it or should I move forward with yet another class or my design is bad from the begin and how it should have been written as?

  • 1
    "Am I overusing Inheritance...?" If you are using inheritance, then you are over-using it. Use composition instead. It will survive the inevitable need to eg have a bag inside a bag, which is thus both a BagItem and EquipmentItem. Inheritance will fail you at that point. – David Arno Oct 27 '15 at 15:14
  • @DavidArno thanks for the comment. I am having a bit of issues on visualizing have a bag inside bag could you elaborate a bit on that? Technically if I make InventoryItem and make both inherit from it, it would be true that both are an inventoryitem but further also something else, i.e a equipmentitem or bagitem. I originally made it this way so I could easily do something like EquippedItems.OfType<CombatEquipment>() but since technically equipmentitem and bagitem dont inherit from anything yet have everything the same except for a property updating both all the time became out of way. – Prix Oct 27 '15 at 15:22
  • 1
    What happens when a character equips an item from their bag? Do you need to create a new EquipmentItem object? What happens to the old BagItem object? – Idan Arye Oct 27 '15 at 15:25
  • @IdanArye BagItem is deleted and EquipmentItem gains a new item – Prix Oct 27 '15 at 16:02
  • When that happens, is there some concrete item passed from the BagItem to the EquipmentItem, or are the relevant fields copied one by one? If, for example, the player is equipping an helmet, is the same Helmet object being referred from both the deleted BagItem and the new EquipmentItem, or are you creating a new EquipmentHelmet object from the old BagHelmet object that'll be deleted after? – Idan Arye Oct 27 '15 at 16:57
6

When I take an item from a bag and hold it in my hand (equipping it) ... do I change the type of the item? Do I change the properties of the item?

No, so this doesn't make sense in the real world (or a game, from the player's POV), which means you're not modelling anything in the problem domain.

Maybe we're modelling something in the solution domain instead? There are problems here too, though:

  • your BagItem doesn't know what kind of slot it can be equipped to. So how can you take something out of the bag and equip it?
  • why does your item need to know what sort of bag it's stored in anyway? Surely you know which actual bag it's in, because you found it somehow, presumably by looking in a bag. So, that information is already available in the context outside the item.

Summary: none of these types seem to be modelling anything useful, but they omit some things you clearly do need. Just use a single type and add features as you actually need them.

5

Inheritance is a tool. If it makes your life easier, use it. The problem is, it's not always clear when to use it and when to use composition.

Consider: What can you inherit?

1) Data : In C++-like languages, you can inherit the data from you parent object and access it.

2) Interface: This is usually why you want to inherit. It's what Java has the notion of interfaces.

3) Code: If you parent defines a "default" version of the code you want, you get the code (and the interface).

So, consider how you use an Item.

You may want to use inheritance because all of your items have the same kind of data: location, weight, mobility, status. Having all of your items inherit from a base class with those attributes will make it easy to think about all Items. This is a good reason to use inheritance: common data that all items have.

  class BaseItem {
      string location;  //What room is the item in?
      int weight;       // for encumbrance
      bool mobility;    // can I move this item?
      bool status;      // dead or alive
  }

  class ArmorItem : public Item {
      int damageReduction;  // ... plus all the other attributes above
  }

  class WeaponItem : public Item {
      int damage; // how much damage this does
  }

Consider for the next example: Are you using it in loops where you do the same thing over and over to it? (This is usually interface inheritance with polymorphism and the reason to use inheritance). In this case, all items inherit the interface of the base class:

 for item in inventory :
      item.print_description()    # All different item types may describe themselves differently

  for item in inventory :
       damage_reduction += item.damage_reducer(CURRENT_DAMAGE_TYPE)   # Some items do nothing, armor items reduce damage

Basically, if you do the same thing over and over to all sorts of different items, and you want different behaviors for the different types of items, inheritance does make sense.

The examples above are usually the canonical ways to use inheritance. Occasionally, you can use inheritance to give you something where almost everything you want is someplace, but not everything. For example, you want all the interface of a complex number class, but you want just one more method which gives you the magnitude2 of the complex. You can inherit from complex (mycomplex) and add a new method. You get all the interface, code, and data from the complex, but augment the class with something you want.

Other discussion on inheritance:
liskov substitution principle Prefer composition to inheritance

People are jumpy about inheritance because it can make code very hard to maintain. But if you can use inheritance because it makes your code simpler, isn't that what tools are for?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.