●前エントリー
多重継承をコンポーネント技術で考える
多重継承を前提に考えなければ・・・
●元ネタ
実装を委譲できる言語を作ればいいのかもしれない
●大元のネタ
http://d.hatena.ne.jp/m-hiyama/20080304/1204615775
(↑の檜山さんの方で何か動きがあるようです。明日以降にエントリーするとかしないとか・・・。楽しみですね)
●まず委譲というのは2通りあります
class A
{
public event EventHandler MouseClick;
public void OnMouseClick()
{
if (MouseClick != null) {
MouseClick(this, new EventArgs());
}
}
}
class B
{
A a = new A();
public B()
{
a.MouseClick += new EventHandler(MouseClick);
}
public void MouseClick(object sender, EventArgs e)
{
Console.WriteLine("マウスが押されました");
}
}
class C
{
B b = new B();
public void MouseClick()
{
b.MouseClick(this, new EventArgs());
}
}
上のコードでクラスAもクラスCもクラスBへ処理を委譲しています。
処理を自分ではなく相手にゆだねるというのが委譲の仕組みです。
インスタンスが必ず関与します。
ただし含まれる方が委譲しているのか委譲されているのかというのは
上記でわかるようにどちらも実現が可能です。
●凪瀬さんと私の会話での委譲
私は凪瀬さんはクラスCを想定していると考えました。
私はこのクラスAの形を私はコンポーネントであると言いました。
そして、よりIDEにサポートされているクラスAを推しました。
この時点で実はコンポーネントが委譲であると気付いていませんでした。
ついさっきふっと気が付きこのエントリーを書くに至りました。
どちらも委譲であったために技術的に交換が可能だったわけです。
●ダイアモンド継承
ここでダイアモンド継承を考えます。
class A { Aの部分 }
class B1 : A { Aの部分+B1の追加部分 }
class B2 : A { Aの部分+B2の追加部分 }
class C : B1, B2 { Aの部分+B1の追加部分+B2の追加部分 }
ここで示したダイアモンド継承のクラスCの中にAの部分は1つしかありません。
私は前エントリーでこのクラスCの中にAの部分が2つ含まれると勘違いしました。
それは委譲で表現するという事から考えたためでした。
委譲というのは先に言ったように2通り書けますが、どちらもかならずインスタンスを介する技術だからです。
この場合ですとB1とB2のインスタンスが必要になり、どちらのインスタンスにもAの部分は含まれます。
本来のダイアモンド継承はインスタンスを介さない継承でしか作り得ない技術なのです。
●凪瀬さんの考える委譲とは
それでも凪瀬さんが委譲でなんとかできるという理由がなんとなくわかりました。
凪瀬さんはさらにこのダイアモンド継承の図の最後のクラスから外向けのインターフェースを
指して委譲で実現できるとおっしゃっているように思いました。
すなわち
class C : B1, B2
{
B1 b1;
B2 b2;
public FuncA()
{
b1.FuncA();
}
}
ここでFuncAはクラスAに含まれるメソッドです。
ここではb1とb2という2つのインスタンスがありメモリ上のAの部分は両方に存在します。
しかしCというクラスを外から見るとクラスCのpublicなFuncAというメソッドは一つです。
そしてこのFuncAがb1かb2のどちらのFuncAを呼び出すかは自由だと言うことだと思いました。
メモリイメージが2つあるというのは論点ではなく、Cから外向きインターフェース上のAの部分が一つになるように委譲でも表現可能であるという意味だと捉えました。
凪瀬さんこれで正解でしょうか?