3

I'm working on a RPG so my character can equip a Weapon, Hat, Boots, Gloves, etc.

So I have an Item class for the different items and the only class who adds new Behaviour is weapon. I'm not sure if is a good idea to extend the class for the different types of items.enter image description here

I think yes because for example, in the Hat slot you can put just Hats so I think it adds safety but I'm looking for an experienced opinion.

Thanks!!

4
  • 8
    Absolutely required reading on that topic: ericlippert.com/2015/05/11/wizards-and-warriors-part-five Read all five parts. – nvoigt Apr 3 '20 at 8:45
  • Great question. i have been doing the same thing, and have been wondering if it is bad or not. Looking forward to some illuminating answers! – Aganju Apr 5 '20 at 15:08
  • 3
    Your model makes no sense to me and even raises the question if you understand the purpose of class inheritance. You have your class tree modeled as if it were a fully dressed game character. I would expect Item to be nearly empty but you have a lot of specific stuff in there. Do boots have health? Does a hat attack? It may be you just made a very original game but more likely you still have trouble with the difference between classes and objects. – Martin Maat Apr 7 '20 at 7:22
  • As agame dev, you may want to follow up the wizards and warriors reading with a chaser of The Universal Design Pattern – Kain0_0 Sep 4 '20 at 7:19
2

Short Answer: there is generally no benefit in creating multiple classes whose methods (and fields) are all identical to each other.

The slightly longer answer is that the primary reason to build different classes into a domain model is to vary behaviour (methods) between those classes. Multiple classes whose behaviour/methods are all identical to each other are generally redundant.

To put it another way, if the only difference between them is their name (and maybe other data), then it would be more typical to set that name and any other varying attributes as values in fields/properties within different instances of one class.

Even while it may be semantically reasonable to make statements about your domain model which suggest that a Hat, Boot or Glove are all different kinds of Item, these are statements about your functional requirements - it does not necessarily follow that the class structure of your code should describe every minor detail or nuance of your domain model. OOP is about creating abstractions by grouping logically-related behaviour and state together.

To that end, there is nothing to be gained by creating a class whose sole purpose is just to have a name which represents data or state; programming languages generally have other simple constructs very well-suited to this such as Enumerations and Constants.

Indeed, the approach of using classes to represent constants does nothing more than add unnecessary rigidity and complexity, not to mention unnecessary code-bloat.

Lastly, try to remember two of the most important principles of software engineering - KISS and YAGNI.

2

I believe that properties and their getters/setters are implementation details which are not very useful when you think about what you can do with objects. When you apply that thinking to the class diagram that you have, everything can be replaced by any container classes (e.g. Array, Dictionary, Map, etc.)

Using the example objects from the your example domain, when we're not thinking about implementation details, we can think about real behaviours. For example, thinking about an Item, one behaviour can be purchase(). Then for Weapon you can add wield() and for others you can add wear(). Item can be the class to be inherited by other classes. It doesn't really matter what price an Item has, anything that can do a purchase operation, can call purchase() without knowing the price.

The second thing I'd like to point out is that thinking about object as nouns often misleads to creating classes which describes the characteristics of the objects but not what can you do with them. So, instead of thinking about Item as something that has price, colour, health, attack, etc. if you think about it as something that can be purchased, it's more straight forward to call the interface Item as Purchasable, which has a purchase() method, and Wieldable interface, Wearable interface, etc.

One concrete example with application of the above is a Weapon class which has a Map to hold its data and implements the Wieldable interface and the Purchasable interface.

0

I have not that much experience with games, but I believe you're on the right track -- I can definitely see some advantages of using classes for the available items.

Let's broaden the picture a bit and add a Player class. A player can own Items. Now let's say, you come up with items in your game, that have a certain, unique logic attached to themselves, a self-destroying tape for example. How would we implement that (this is pseudo code, but you'll get the picture):

class Player
  def items
    # returns an array of items the person posesses
  end

  def use_item(item)
    item.use(self)
  end
end

class Item
  def use(player)
    # invoked when a person uses an item
  end
end

class Hat < Item
# Simple inheritance, no additional functionality
end

class SelfDestroyingTape < Item
  # use() overriden
  def use(player)
    player.items.remove(self)
  end
end

playerOne.use_item(hatInstance)
playerOne.use_item(selfDestroyingTapeInstance)

This way, you can encapsulate the item logic properly in their respective classes. Another use case might be to codify how well a player uses a certain item, e.g. how accurate they use a weapon in order to maintain a player high score or some global statistics/leaderboard.

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.