クラスの分散

[戻る]
シルク法度 2002/10/31(木) 22:28:30
いつもお世話になります。
シルク法度です。

今回は、クラスの分散について質問があります。
MFCのクラスを継承して、メソッドを追加していると、
どんどんクラスの規模が大きくなり、クラスが巨大化してしまいます。
クラスは、ひとつの目的を持ったもので、複数の目的を持たないようにしなければ
いけないのですが、MFCのクラスがもつメソッドを使用する処理のため、
どうしてもそのクラスに新しくメソッドを追加してしまいがちになります。

たとえば、今テキストエディタを作成していて
CRichEditCtrl を継承していろいろと機能を追加しています。
エディタの文字を取得したり、設定したりするメソッドが CRichEditCtrl 
にあるため、それを用いた処理はどうしてもCRichEditCtrl  の継承クラスに
実装してしまい、結果として、ものすごい量のメソッドをつ
巨大クラスになってしまいました。以下のような解決方法を考えましたが、
この方法はいいんでしょうか?なかなか自分では判断できないので、
皆さんの意見を聞きたいのですが…

****************************************************************
解決方法

CRichEditCtrl のもつメソッドはPublicであるので、
そのポインタ(例えば、m_pEditCtrlとする)をもつクラスを定義してそれに
処理をやらせる。
しかし、この方法だと、たとえば、GetSel()などで、カレット位置を取得したい場合、
いちいち
m_pEditCtrl->GetSel() 
などと書かなければいけないので、
現状あるソースをこのクラスに移動するとき手間がかかる。
そこで、
以下のように、MFCのメソッドと同じ名前のメソッドを定義し、その中で、
本当のMFCのメソッドを呼び出すようなクラスを作成する。

GetSel(sel){  m_pEditCtrl->GetSel(sel) }
SetSel(sel){  m_pEditCtrl->SetSel(sel) }
・・・


それを継承させたクラスに、巨大クラスから必要なメソッドを
移動する。この移動したメソッドでは、SetSel()などのMFCのメソッドが使用されているが、
上記のように、定義されているため、ソースを書き直す必要はない。


実際にこの分散クラスを使用するには、まず、
処理を行う場所で、一時的にこのクラスのオブジェクトと生成して、
処理を行わせ、終わったら削除するようにする。
ただし、この分散クラスでは、
巨大クラスのメンバ変数の値を使用したり、変更したりすることもあるので、
分散クラスのコンストラクタで、巨大クラスのメンバ変数を取得し、
処理後、デストラクタで巨大クラスに変更を反映する。
*****************************************************************************

この方法の欠点は、GetSel(sel){  m_pEditCtrl->GetSel(sel) }
などのような、処理を行うクラスを定義しなければいけないことで、
当然、使用するすべてのメソッドについて、定義しなければならないことです。
ただ一度定義してしまえば、このクラスは使いまわすことができるので、
便利だとは思うんですが。…

何かもっとほかの便利な方法はないでしょう?
もしあれば、教えてください。



MFCの質問ではないので、掲示板の主旨とは異なるかもしれませんが、
よろしくお願いします。

dairygoods 2002/11/01(金) 09:48:55
最初から分けて作るのであれば、シルク法度さんの方法で良いと思います。
修正量が少ない分け方としては、こんな方法はどうでしょうか。

その1) 機能の細かさで分ける

class A : public CRichEditCtrl
{
  // CRichEditCtrlとA自身のメンバを使用する関数
};

class B : public A
{
  // CRichEditCtrl,A,Bのメンバを使用する関数
};

class C : public B
{
  // CRichEditCtrl,A,B,Cのメンバを使用する関数
};


その2)機能の種類で分ける

class Base : public CRithEditCtrl
{
  // 派生クラスで使用する関数と変数
};

class A : public Base 
{
  // 機能Aに関係する関数
};

class B : public Base 
{
  // 機能Bに関係する関数
};

class C : public Base 
{
  // 機能Cに関係する関数
};

C言語のキャストの仕組みを悪用した方法。
A,B,Cにメンバ変数があると正しく動きません。
Base edit;
と定義しておいて、使いたい機能の型にキャストして使います。

古いスレッドには追加発言できません。