Herb Sutter と Andrei Alexandrescu が著書C++ Coding Standards (item 34)friend
で説明しているように、継承は、C++ を使用して 2 つのクラス間で使用できる最も緊密な関係の 1 つであり、クラス間の関係に次ぐものです。
OOの SOLID 原則によると、成功する設計はクラス間の疎結合を目指す必要があります。これは、依存関係を最小限に保つことを意味します。これは、継承が注意して使用する必要があるツールであることを意味します。
もちろん、通常、依存関係はどこかinterface
に存在する必要があるため、実装をまったく行わないクラスから継承することも妥当な妥協案です ( C# や Java などの言語でのいわゆるs に似ています)。例えば
class IDriveable
{
public:
virtual void GoForward() = 0;
virtual void GoBackward() = 0;
};
class Car : public IDriveable { /* etc. */ };
class Bus : public IDriveable { /* etc. */ };
class Train : public IDriveable { /* etc. */ };
このアプローチでは、複数のDrivableクラス間で再利用されるコードの要素がある場合、通常、構成またはその他の弱い関係を使用して、繰り返されるコードを排除します。たとえば、 aと aの
コードを再利用したいが、左に回すのが非論理的である a ではなく、 andのメンバーである別のクラスになる可能性があります。TurnLeft
Bus
Car
Train
TurnLeft
Bus
Car
- さらに、あいまいに関連するすべてのクラスについて知る必要がある機能は、クラス階層の外部にあり、核心的な実装の詳細ではなく、インターフェイス/ベースのみを認識します。
最終的には、合成用の少量の余分なコードが追加される可能性がありますが、多くの場合、設計はそれほど複雑ではなく、通常は管理が容易になります。このようなコードを設計するための厳格なルールはありません。これは、解決しようとしている固有の問題に完全に依存するためです。
密結合なしでコードを再利用する方法は他にもあります。テンプレートを使用すると、純粋なvirtual
関数を含む空のクラスを使用せずにインターフェイスを暗黙的に定義できます (テンプレートは追加の型安全性を提供します。これは非常に良いことですが、構文的にはもう少し複雑です)。
std::function
そして、より機能的なスタイルでコードを再利用するためにラムダを使用できる方法があります。通常、関数オブジェクトを渡すときに密接な依存関係は関係ありません。