October 04, 2004
奥さん知ってました? C#ではクラス宣言をネストできるんですって!
C#ではクラス宣言のネストができるということを知った。というか今まで知らなかった。調べてみるとjavaでもできるらしい。
で、ネストするとどうなるかというと、内側にあるクラスから外側のクラスのprivate領域にアクセスできるようになる。
namespace Test
{
public class Outer
{
private int outerPrivateValue;
public Outer(int i)
{
outerPrivateValue = i;
}
public Inner CreateInner()
{
return new Inner(this);
}
public class Inner
{
Outer outer;
public Inner(Outer outer)
{
this.outer = outer;
}
public int GetOuterPrivateValue()
{
return outer.outerPrivateValue;
}
}
}
}
この例だと、InnerクラスのGetOuterPrivateValueのなかで、Outerクラスでprivate宣言されたouterPrivateValueにアクセスしている。C++ではfriendという宣言があって、指定したクラスに対してprivate領域へのアクセスを許可することができた。friendはC#には無いみたいで、friendと同じことをさせるためにこの仕様ができたのかしらん。
上に挙げたコードを次のようにして使うことができる。
Outer outer = new Outer(123); MessageBox.Show(outer.CreateInner().GetOuterPrivateValue().ToString());
で、上の例だとこの仕様がどううれしいのかがちっとも分からない(OuterクラスにouterPrivateValueを公開するインターフェースを付けるのとなんら変わらない)わけで、こんな仕様をどうやって使うのかという疑問が当然でてくる。これについては、たとえばmsdnの『コレクションクラスのチュートリアル』の中に載っている、IEnumeratorインターフェイスIEnumerableインターフェイスの実装例を挙げることができる。
ここで紹介されているコードでは、TokenEnumeratorクラスが
private class TokenEnumerator : IEnumerator
と宣言されている。アクセス識別子がprivateになっているのがキモで、これによってクラスそのものが外部から隠蔽されている。で、外部へTokenEnumeratorのインスタンスを渡すときには、IEnumeratorとして渡されるようになってる。
public IEnumerator GetEnumerator()
{
return new TokenEnumerator(this);
}
これによってTokenEnumeratorの存在を外部に知らせずに、「IEnumeratorインターフェースを実装したなにか」という情報のみを公開することになるので結合を疎にすることができてオブジェクト指向的にすばらしいというわけだ。こういうのを知ると「オブジェクト指向ってすばらしい!」とか「C#をもっとちゃんと勉強しとかないとなあ」とか思って向学心が湧いてきてナイス。う〜ん、美しい。
Trackback
You can ping this entry by using http://windy.ac/MT/mt-tb.cgi/566 .
