Vous avez déjà quelques bonnes réponses, mais l’énorme éléphant dans la pièce de votre question est celui-ci:
entendu quelqu'un dire qu'il faut éviter l'utilisation de l'héritage et utiliser plutôt des interfaces
En règle générale, lorsque quelqu'un vous donne une règle empirique, alors ignorez-la. Cela vaut non seulement pour "quelqu'un qui vous dit quelque chose", mais aussi pour lire des choses sur Internet. À moins que vous ne sachiez pourquoi (et que vous puissiez vraiment le supporter), un tel conseil est sans valeur et souvent très dangereux.
D'après mon expérience, les concepts les plus importants et les plus utiles de la programmation orientée objet sont "faible couplage" et "forte cohésion" (les classes / objets se connaissent le moins possible les uns sur les autres et chaque unité est responsable du moins de choses possible).
Faible couplage
Cela signifie que tout "paquet" de votre code doit dépendre le moins possible de son environnement. Cela vaut pour les classes (conception de classes) mais aussi pour les objets (implémentation réelle), les "fichiers" en général (c'est-à-dire le nombre de #include
s par .cpp
fichier, le nombre de fichiers import
par .java
fichier, etc.).
Un signe que deux entités sont couplées est que l'une d'entre elles va se briser (ou doit être modifiée) lorsque l'autre est modifiée de quelque manière que ce soit.
L'héritage augmente le couplage, évidemment; changer la classe de base change toutes les sous-classes.
Les interfaces réduisent le couplage: en définissant un contrat clair, basé sur une méthode, vous pouvez modifier librement tout ce qui concerne les deux côtés de l'interface, à condition de ne pas modifier le contrat. (Notez que "interface" est un concept général, le langage Javainterface
classes abstraites ou C ++ ne sont que des détails d'implémentation).
Haute cohésion
Cela signifie que chaque classe, objet, fichier, etc. soit concerné ou responsable du moins possible. Autrement dit, évitez les grandes classes qui font beaucoup de choses. Dans votre exemple, si vos armes ont des aspects complètement séparés (munitions, comportement de tir, représentation graphique, représentation d'inventaire, etc.), vous pouvez avoir différentes classes qui représentent exactement l'une de ces choses. La classe d'arme principale se transforme alors en "détenteur" de ces détails; un objet d'arme n'est alors guère plus que quelques indications sur ces détails.
Dans cet exemple, vous vous assurez que votre classe représentant le "comportement de tir" en sait le moins possible sur la classe d'armes principale. De manière optimale, rien du tout. Cela signifierait, par exemple, que vous pourriez donner un "comportement de mise à feu" à n'importe quel objet de votre monde (tourelles, volcans, PNJ, etc.) en un claquement de doigt. Si, à un moment donné, vous souhaitez modifier la manière dont les armes sont représentées dans l'inventaire, vous pouvez simplement le faire - seule votre classe d'inventaire en est consciente.
Un signe qu'une entité n'est pas cohérente est qu'il grandit de plus en plus, se ramifiant dans plusieurs directions en même temps.
L'héritage tel que vous le décrivez diminue la cohésion. Vos classes d'armes sont, en fin de compte, de gros morceaux qui gèrent toutes sortes d'aspects différents et non liés de vos armes.
Les interfaces augmentent indirectement la cohésion en séparant clairement les responsabilités entre les deux côtés de l'interface.
Que faire maintenant
Il n'y a toujours pas de règles strictes, tout cela n'est que des directives. En général, comme l'utilisateur TKK l'a mentionné dans sa réponse, l'héritage est beaucoup enseigné à l'école et dans les livres; ce sont les choses fantaisistes sur la POO. Les interfaces sont probablement plus ennuyeuses à enseigner et aussi (si vous dépassez des exemples triviaux) un peu plus difficiles, ouvrant le champ de l'injection de dépendance, qui n'est pas aussi nette que l'héritage.
En fin de compte, votre système fondé sur l'héritage est toujours préférable à l'absence de conception claire de la POO. Alors n'hésitez pas à vous en tenir à cela. Si vous le souhaitez, vous pouvez réfléchir / google un peu sur le couplage faible, la cohésion élevée et voir si vous souhaitez ajouter ce type de réflexion à votre arsenal. Vous pouvez toujours refacturer pour essayer cela si vous le souhaitez, plus tard; ou essayez des approches basées sur une interface sur votre nouveau module de code plus grand.