Composition versus Inheritance for building a Monster class

I’m creating an RPG that has some monsters. There is a BaseMonster class that contains some fields and methods specific to all monsters, and then a single Monster class that represents an instantiated monster which will have some data specific to it, which is set at runtime. Im essentially stuck on how to structure these classes.
The obvious approach is to have Monster inherit from BaseMonster (i.e. class Monster : BaseMonster) but I’m always hesitant with inheritance so I wanted to try a composition approach where Monster has-a BaseMonster (ie. class Monster {
BaseMonster baseMonster;

})

This would be loosely coupled but intuitively doesn’t make sense. Am I overthinking this? which is the better option?

Not sure why there needs to be any composition or inheritance here. It’s just fine if the Monster both has the shared stuff and the runtime stuff in it. So I’d just have Monster.

If the shared things in BaseMonster are editable at edit time (ie. they’re in a ScriptableObject), It’d make sense for that to be PersistentMonsterData or something, in which case it’d make sense for Monster to have one.

I forgot to mention this. The BaseMonster data is loaded via a JSON. So If I had a single class, all the data specific to Monster (which is generated at runtime, at some unknown time) would all be set to null or some default value, since the JSON data would only contain BaseMonster stuff.

So all the BaseMonster fields would be set with the JSON data and the rest of the Monster specific stuff would be null or blank. I don’t like that idea because I think it could cause some issues down the line where something tries to access Monster specific data and gets some garbage default data because the Monster data hasn’t been set yet

Yeah, in that case I would for sure use composition.

The important part here is that you probably want the data you load from the Json file to be immutable, for two reasons;

  • it’s could lead to confusion if you look at the json-file, and a monster isn’t behaving like it looks like it should in the file.
  • it’ll allow you to share a single instance of the loaded data between all the monsters using it, saving memory, and making hot-reloading simpler and faster.

So I’d for sure have Monster have the data as a member. I wouldn’t still give the loaded data some name that reflects that it’s a bundle of loaded config data, and not actually a Monster

Yep, got it. Thanks