これは退屈な学術的なOOPの質問の1つですが、宿題ではありません。初心者プログラマーから、OOPに関する愚かな教科書の例の1つについて質問を受けました。
SquareクラスとCubeクラスを設計していると想像してください。どちらがどちらを継承する必要がありますか?
私は関係を見ます、しかしそれが何であるか、私は本当に見ることができません!
OOPを念頭に置いて論理的な議論をしていただけませんか。
ない!正方形は立方体ではなく、立方体も正方形ではないため、どちらも他方から継承する必要はありません。正方形は多角形から継承でき、立方体は多面体から継承できますが、この 2 つ自体は相互に排他的です。
継承はありません。継承は "is-a" 関係です (以下のリンクで説明されているように、"is-a" 関係ではない場合もあります)。立方体は正方形ではなく、正方形は立方体ではありません。
どのように構築するかは、モデル化の方法によって異なります。立方体に 6 つの正方形があるようなもの (立方体はそうではありません。6 つの正方形があります。構成)、または立方体には正方形のように側面のサイズがあります。しかし、「is-a」がなくなると、継承は危険地帯になります...
また、継承では、基本クラスで有効なものはすべて、派生クラスでも有効でなければなりません。それは正方形が長方形を拡張する問題です。例えば:
Cube が Square を継承すると仮定すると、Square にメソッド changeArea(double area) と getSide() がある場合、Cube でも同じことが可能です。しかし、立方体の面積は正方形の面積の 6 倍なので、そうではありません (正方形が 6 個あります)。
Square が Cube を継承すると仮定すると、Cube に setVolume(double volume) メソッドがある場合、ボリュームがなくなると正方形が壊れます。
最後に、継承を使用する場合は、GeometryObjectWithEqualSidesオブジェクトを作成すると、両方がそれを継承できます。:)
正方形と立方体は、同じクラス「ハイパーキューブ」の2つのインスタンスであると主張できます。これには、点(0次元)、線分(1次元)などが含まれます。次元の数と片側の長さは、Hypercubeの特定のインスタンスを定義するのに十分です(もちろん、n次元の原点と方向を追加することもできます)。
ハイパーキューブは、その特定のインスタンスの頂点、エッジ、面などの数の値を返す関数/メソッドを提供できます。
詳細については、ウィキペディアのHypercubeを参照してください。
どちらもハイパーキューブから継承します
struct Square // Rectangle actually
{
Square( int dx, int dy ) : dx(dx), dy(dy) {};
int dx;
int dy;
int floor_area() { return dx*dy; };
};
struct Cube : Square // Cuboid actually
{
Cube( int dx, int dy, int dz ) : Square(dx, dy), dz(dz) {};
int dz;
int cube_area() { return floor_area()*2+dx*dz*2+dy*dz*2; };
};
ここでは、リスコフの置換原理が破られていないようです。
どちらも他方を継承すべきではありません。1 つは 2 次元の形状で、もう 1 つは 3 次元のオブジェクトです。継承を正当化するのに十分な類似性が 2 つの間にありません。
各辺に個別のオブジェクトが必要な場合は、正方形で構成された立方体を作成することも考えられます;)
ここにあるコメントのほとんどは、どれも別のものから継承すべきではないと正しく言っています。これはほとんどの場合に当てはまります。しかし、より一般的な答えがあると思います。 それは、それらに対する期待に依存します。 Squareが何をすることを期待していますか?キューブもやってるの?逆かもしれません。Cube を使用するときはいつでも Square を使用できますか? 私は、「Cube は Square と同じことをすべて実行する」、「Square は Cube と同じことをすべて実行する」というステートメントはどちらも常識的に間違っていると思います。ただし、プログラムの動作とその構成要素を定義するのはユーザーであるため、その構造と動作を決定するのはユーザー次第です。
おそらく、「立方体には 6 つの正方形が含まれる」という関係が見られます。