あなたはすでにいくつかの良い答えを得ましたが、あなたの質問の部屋にある巨大な象はこれです:
継承を使用することは避けなければならず、代わりにインターフェイスを使用する必要があると誰かから聞いた
経験則として、誰かがあなたに経験則を与えた場合、それを無視します。これは、「誰かが何かを言っている」だけでなく、インターネット上のものを読む場合にも当てはまります。理由がわからない(そして実際にその背後に立つことができる)場合を除き、このようなアドバイスは価値がなく、しばしば非常に有害です。
私の経験では、OOPで最も重要で有用な概念は「低結合」と「高凝集」です(クラス/オブジェクトは互いについての情報をできるだけ少なくし、各ユニットの責任はできるだけ少なくします)。
低カップリング
これは、コード内の「ものの束」が周囲にできるだけ依存しないことを意味します。これはクラス(クラス設計)だけでなく、オブジェクト(実際の実装)、一般的な「ファイル」(つまり、#include
単一.cpp
ファイルあたりのs 数、import
単一.java
ファイルあたりの数など)にも当てはまります。
2つのエンティティが結合されているという兆候は、他のエンティティが何らかの方法で変更されたときに、一方が壊れる(または変更する必要がある)ということです。
継承は明らかに結合を増加させます。基本クラスを変更すると、すべてのサブクラスが変更されます。
インターフェイスは結合を減らします。明確なメソッドベースのコントラクトを定義することにより、コントラクトを変更しない限り、インターフェイスの両側について自由に変更できます。(「インターフェース」は一般的な概念であり、Java interface
またはC ++抽象クラスは単なる実装の詳細であることに注意してください)。
高い凝集力
これは、各クラス、オブジェクト、ファイルなどをできるだけ気にせず、責任を負わせないことを意味します。つまり、多くのことを行う大規模なクラスは避けてください。あなたの例では、武器が完全に独立した側面(弾薬、発射行動、グラフィック表現、インベントリ表現など)を持っている場合、それらの1つを正確に表すさまざまなクラスを持つことができます。メインの武器クラスは、これらの詳細の「ホルダー」に変換されます。その場合、武器オブジェクトはそれらの詳細へのいくつかのポインタにすぎません。
この例では、「発火行動」を表すクラスが、メインの武器クラスについて人間に可能な限りほとんど知らないようにします。最適には、何もありません。これは、たとえば、指のスナップだけで、世界のあらゆるオブジェクト(タレット、火山、NPCなど)に「発射動作」を与えることができることを意味します。ある時点で、インベントリで武器がどのように表現されるかを変更したい場合は、単純に変更できます。インベントリクラスのみがそれを知っています。
エンティティが凝集していないという兆候は、エンティティがますます大きくなり、同時に複数の方向に分岐する場合です。
継承は、凝集性を低下させます-結局のところ、武器クラスは、武器のあらゆる種類の無関係な側面を処理する大きな塊です。
インターフェースは、インターフェースの両側の責任を明確に分離することにより、間接的に結束力を高めます。
今何をする
厳格なルールはまだありません。これはすべて単なるガイドラインです。一般的に、ユーザーTKKが答えで述べたように、相続は学校や本でたくさん教えられています。それはOOPについての素晴らしいものです。インターフェイスはおそらく教えるのがより退屈であり、(些細な例を過ぎた場合)少し難しくなり、継承ほど明確ではない依存性注入の分野を開きます。
結局のところ、継承ベースのスキームは、明確なOOPデザインをまったく持たないよりも優れています。だから、それに固執すること自由に感じなさい。必要に応じて、低結合、高凝集について少し反論/グーグルし、その種の考え方を武器に追加したいかどうかを確認できます。必要に応じて、いつでもリファクタリングして試すことができます。または、次に大きなコードの新しいモジュールでインターフェイスベースのアプローチを試してください。