Visualization Tool Kit(VTK)など

※実装目的によって解が異なることを理解して読むこと.

長方形は正方形を抽象化したものか

よくスーパークラス(A)とサブクラス(B)の関係はB_is_Aとなっていることが求められると言われる.
では正方形は長方形のサブクラスとすべきであろうか.

下記はよくある多重継承(他に適切な言葉がない)の説明に使われる設計である.
class Quadrangle {};
class Rectangle : public Quadrangle {};
class Rhombus : public Quadrangle {};
class Square : public Rectangle, public Rhombus {};

四角形クラスがスーパークラスとしてあり,長方形や菱形に派生している.
長方形と菱形両方の性質をもっているので正方形はその両方をスーパークラスとしてもつ.

しかしながら,この例を書く人は実装まで考えていないのだろう.

class Quadrangle
{
public:  
  //省略
protected:
  std::array<Point, 4> vertex;
};
class Rectangle : public Quadrangle
{
public:
  Rectangle();
  void SetWidth(const double value);
  void SetHeight(const double value);
  void SetCenter(const Point& value);
};
class Rhombus : public Quadrangle
{
public:
  void SetSideLength(const double value);
  void SetAngle(const double angle, const Point& target_vertex);
  void SetCenter(const Point& value);
};
class Square: public Rectangle, public Rhombus 
{
  
};


さてRectangleクラスの定義には色々な設計ができるだろうが,縦の長さ,横の長さ,位置の設定はできるだろう.
それを直接保存するか,頂点情報に変換して保存するか程度の違いである.
Squareクラスには何も宣言していないが,Rectangleクラスをスーパークラスとして書いた後に,
何を宣言すべきかわからなくなったからである.

Squareに必要なインターフェイスは「辺の長さ」と「位置」である.
RectangleやRhombusが持つ他の関数はSquareにとって必要のない関数となるのである.

問題点と納得できる設計

そもそも正方形を抽象的にしたものが長方形なのかというところに疑問がある.
条件の一部が同じというだけで長方形は幅と高さを独立して設定できる必要があり,正方形は独立して設定できない.
これは親子関係にあるとしてよいのだろうか.

たしかに正方形は長方形の条件を満たすが,長方形を生成するRectangleクラスとしては振舞えない.
その点にこの問題の肝がある.

そこで下のように設計する.


class Quadrangle;
class Rectangle;
class Rhombus;
class Square;

class Rectangle : public Quadrangle
{
public:
  Rectangle(const Square& other);
  Rectangle& operator=(const Square& other);
};

class Rhombus : public Quadrangle
{
public:
  Rhombus(const Square& other);
  Rhombus& operator=(const Square& other);
};

class Square : public Quadrangle {};


正方形は長方形や菱形に変換できるが,長方形や菱形の全ての機能を継承するわけではないから親子関係にはないとするのである.

似たような例

似たような例にboost::ublas::identity_matrixがある.

identity_matrixは
  • 正方行列である
  • i == jの場合は1, i != jは0である
という条件を満たす.

一見,matrixの派生クラスとできそうだがこれは長方形と正方形の関係に非常によく似ている.
ではBoostでの実装はどうなっているかというと


template<class T, class L, class A>
class matrix : public matrix_container<matrix<T, L, A> > {};

template<class T, class ALLOC>
class identity_matrix: public matrix_container<identity_matrix<T, ALLOC> > {};


となっている.これは先程の正方形・長方形の例と同様である.

コメントをかく


「http://」を含む投稿は禁止されています。

利用規約をご確認のうえご記入下さい

Menu

メニュー

チュートリアル

アルゴリズム(数学)

並列計算

STL

#include<memory> #include<string> #include<sstream> #include<algorithm> #include<functional> #include<numeric>

Media Foundation

【メニュー編集】
Wiki記法ガイド

メンバーのみ編集できます