Thank you all for your responses.
I've been thinking about this problem for a little while and I've decided to pursue the following approach.
All mobiles, items, corpses, etc. are simply Entities. The Entity class contains a private hash map of enum => int:
{
MOBILE => 1,
RED => 1,
DRAGON => 1,
BASE_HP => 800,
FLYING => 1
}
If it dies, then it's easy to just add a CORPSE to the hash map
{
MOBILE => 1,
RED => 1,
DRAGON => 1,
BASE_HP => 800,
FLYING => 1,
CORPSE => 1
}
The values are integers to allow composition (e.g. metal, silver) and stats (e.g. hp, str, dex) to be stored in this hash table. The Entity class will have a ton of methods such as isCorpse(), getHp(), isFlying(), etc. to make programming easier.
A lot of really odd combinations could be possible (e.g. a flying undead potion that can be wielded) but I think a really flexible entity system that allows transmutations rather than fixed classification system will serve me better.
The game state will maintain a single list of all Entities but I'll have a few convenience lists holding references to make key iterations easier i.e. there will also be a list containing all alive mobiles, another containing all the party members, one for all items on the ground, etc.
Keeping these lists in sync is easy because I only need to update them if an entity transmutes i.e. a key is added or removed.