October 04, 2004

奥さん知ってました? C#ではクラス宣言をネストできるんですって!

Posted at October 4, 2004 01:22 AM in .

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 .

Comments

Post a comment










Remember personal info?