Hi! I'm new to this forum, I hope my stay will be pleasant for everyone involved. =) I place my question here since it's more a question on how to design an interface in a "good practice" way, than solving a game making problem.
To clearify: the Item class is an inanimate thing that can exist in the world and in an inventory of any kind. The Action class is a class that uses the methods of the Item class and references to other objects like the position in the world, the player, the target, etc, to produce effects and actions. The seperation is motivated by me wanting to reuse code for actions that happen across a wide range of objects, and also keep the effects modular.
I am designing an Item interface in a game I'm making. My main issue is that I have tried to make the interface clean with only a few methods because I want it to be easy for the person implementing subclasses of the Action class, as it will need to contain implementations that use this interface. I have seen other games having massive item/object interfaces with lots of isX() methods and methods that doesn't really apply to the object behind it all. I find such solutions marginally better than instanceof and casting, since they both use if clauses to a large extent.
But I am stumped with the question on how to solve Item "inventory". Memory overhead is a real issue since these items will number in millions, and even if many will just be references to static Items, inventory Items will need to have a list/array of some kind that must be in an specific instance. So I want to avoid having an object handle these inventory methods because it carries additional memory overhead beyond the actual array or list. This List/Array will contain Items, but not all items will have such inventories. Therefore I find it ugly to have about 5 methods about just how to manipulate this list/array in the actual Item interface, as only a few will use it. Even if the potential to cause bugs on the action implementing side is not that big, it's still ugly and I feel an Item should be more abstract than this. I could have just made an abstract Inventory class and have some Items extend this, as the inventory related methods would mostly use the same implementation, and then connect to the subclasses by overridding a method so the actual variables for inventory size and such would be reachable by this superclass, but this would only make implementation of inventory Items easier, it will still leave a bloated and messy interface, and I anticipate more methods for other different aspects could also start appearing if I don't restrict this watering down of the abstraction and it could turn out a mashup of different possible subclasses! I think any class should avoid having methods that is not relevant for the contained object.
My Proposed solution is just having a way to check if the item has an inventory, and then if it has it then the implementer in a action class either checks if it is an inventory, or knows this because of
testing earlier than the scope of this Action. Then the implementer would feed the Item in question to the desired methods that would now instead reside in an abstract helper class that now gets the list and important variables from the Item. The solution makes the list public and I don't really like that in a way, but now all methods in Item have a purpose and the number of methods has decreased.
Is there another way of doing this or is there some flaw in my reasoning that any of you experienced programmers notice? I'm selflearned and have no idea of what is the best practise but I know I prefer interfaces to not contain hundreds of methods. =) Are classes like my outlined helperclass to be avoided? I feel there is something fishy about spreading out the implementation of the Item behaviour outside the class scope... Perhaps making it an internal class or being careful in designing the package so this behaviour is emphasised?
Any ideas, tips that come to mind?