私はしばらくの間、この設計上の問題に苦労してきました。私が何をしようとしているのか、私が見たさまざまなアプローチ、何をしようとしているのか、そしてその理由を説明するために最善を尽くします.
私は同じ種類のオブジェクトを繰り返し扱う科学計算環境で働いています。太陽系を含む銀河を想像してみてください。各太陽系には惑星系が含まれ、各惑星系には月が含まれます。この目的のために、私は状況を「ある」状況と考えています。したがって、構成を使用して、銀河にその太陽系へのアクセスを与え、各太陽系が月にアクセスできる惑星系にアクセスできるようにしました。各カテゴリ:独自のクラスであること。
私が取り組んでいるさまざまな問題には、これらのオブジェクトに関するさまざまなタイプのデータが含まれていることがよくあります。そして、さまざまなタイプのデータが利用可能になると、オブジェクトを使って特定のことができるようになります。したがって、データ型 1 を使用できる場合は、次のクラスを作成します
class GalaxyOne { /* … */ };
class SolarSystemOne { /* … */ };
class PlanetOne{ /* … */ };
class MoonOne{ /* … */ };
そして、データ型 2 を利用できるようになったら、作成します
class GalaxyTwo { /* … */ };
class SolarSystemTwo { /* … */ };
class PlanetTwo{ /* … */ };
class MoonTwo{ /* … */ };
各クラスの複合的な側面は、含まれているクラスへのポインターを含むベクトルなどのコンテナー変数を使用して処理されます。たとえば、各 Galaxy クラス内で見つけることができます。
class GalaxyTwo{ /* … */
protected:
std::vector<SolarSystemTwo*> solarSystems;
/* … */
};
クラスをより高次のクラスに結合したい場合に困難が生じます。
class GalaxyOneTwo: public GalaxyOne, public GalaxyTwo{
/* Additional methods */
};
ただし、GalaxyOneTwo には GalaxyOne と GalaxyTwo のバージョンがあるため、solarSystems ベクトルにあいまいさの問題が生じます。さらに、継承するベクトルには、SolarSystemOneTwo 型ではないオブジェクトへのポインターが含まれています。これは必須です。そこで、すべてのコンテナ変数を配置した場所からすべてのオブジェクトが継承するテンプレート クラスを作成できると考えました。
template<MoonT,PlanetT,SolarSystemT>
class PrimitiveGalaxy {
private:
std::vector<SolarSystemT*> solarSystems
};
class GalaxyOne: public PrimitiveGalaxy <MoonOne,PlanetOne,SolarSystemOne>{
/* No longer defining any container variables for composition */
};
このアプローチは、これらの基本的な Galaxy タイプ (GalaxyOne および GalaxyTwo) に対して非常にうまく機能します。ただし、結合された銀河タイプを作成しようとすると、あらゆる種類のあいまいさが生じます。
class GalaxyOneTwo: public GalaxyOne, public GalaxyTwo, public PrimitiveGalaxy<MoonOneTwo,PlanetOneTwo,SolarSystemOneTwo>{
/* … */
};
GalaxyOneTwo で定義された任意のメソッド内で solarSystems を使用すると、あいまいになります。これは、GalaxyOne と GalaxyTwo から継承された各バージョンで 1 回、GalaxyOneTwo で 3 回の 3 回定義されているためです。
具体的に使用することで、このあいまいさを取り除くことができます
PrimitiveGalaxy::solarSystems
毎回適切なベクトルを参照する必要がありますが、多くの余分な入力と構文が必要になるため、これは望ましくありません。
私は銀河の各タイプと原始銀河との間の友情を使用することを検討しましたが、これには同様のレベルの詳細な記述が必要です.
名前空間がコードの記述を簡素化する可能性があるという予感がありますが、GalaxyOneTwo に対して定義された名前空間内で、solarSystems への参照が PrimitiveGalaxy::solarSystems への参照になるように名前空間を定義する方法がわかりません。
編集:
GalaxyOne と GalaxyTwo の唯一の違いは、solarSystems に含まれるクラスのタイプではないことに注意してください。各クラスは銀河に関連するさまざまなデータを扱うため、多くの違いがあります。したがって、さまざまな状態変数、それらの状態変数のゲッターとセッター、およびデータを計算して出力するメソッドを持つさまざまなクラスを作成します。solarSystems は、問題を引き起こしている機能の例であるため、ここで説明しました。GalaxyOneTwo が作成されると、GalaxyOne と GalaxyTwo で使用されるのと同じデータが使用されるため、それらの変数とメソッドをすべて継承したいと考えています。また、データはさまざまな方法で組み合わせることができるため、GalaxyOneTwo 内でそのための新しいメソッドを作成する必要があります。これらは、私が継承を使用するようになった多くの違いの一部です。そうは言っても、問題を引き起こすのは、構成を可能にするコンテナ変数です。各 solarSystem クラス内には、惑星へのアクセスなどを可能にする同様のベクトルがあります。
編集:
ここで一般的に私の設計哲学に特化した質問については(現在の設計の試みを解決しようとすることに重点を置いたこの質問とは対照的に)、次のリンクを参照してください 。