入れ子にされた型-内部クラス
内部クラスとは、クラスの内部にクラスを定義する機能である。
クラスの内部にクラスを定義することにより、、クラス間の関係をクラスの継承関係とはまた別の意味で、従属関係,親子関係で表現したい時に便利。
内部クラスにprivate修飾子を付ける事により、他のクラスからアクセスできないようにクラスを隠蔽するこができる。
c#の内部クラスは「入れ子にされた型」と呼ばれ、型の内部に型を定義できるという位置付けになる。
内部クラスを多重にネストする事もできる。
C#の内部クラスはjavaと違って単純である。
クラスの中にクラスをただ定義するだけ。
内部クラスの例を以下に示す。
リスト1(Program.cs)
内部クラスの継承
クラスを継承する事により、サブクラスからスーパクラスの内部クラスにアクセスできるようになる。
以下の例は、リスト1のコードを修正して、内部クラスを含むクラスOuterClassを継承したクラスOuterClassExより、OuterClassで定義されている内部クラスInnerClassにアクセスする例である。
リスト2(Program.cs)
内部インターフェース
クラスの内部に、インターフェースを定義する事もできる。
以下にその例を示す。
リスト3(Program.cs)
逆に、Javaのようにインターフェースの内部にクラスを定義する事はできない。
以下のようなコードはエラーになる。
リスト4-エラーになるコード
クラスに属するインターフェースを定義する事に意味はあっても、インターフェースに属するクラスを定義する意味は無いという事なのだろう。
内部クラスとトップレベルクラスのアクセス修飾子
内部クラス(内部インターフェース)のアクセス修飾子には、public、private、protected、および internal(アセンブリ外からのアクセスが禁止される)のすべてを指定できる。
これに対して、名前空間の直下にある、他のクラスにネストされていないクラス(トップレベルクラス)には、public または internal のみが指定できる。
トップレベルクラス(トップレベルインターフェース)のアクセス修飾子の指定を省略すると、internalになる。
これに対して、内部クラスの アクセス修飾子の指定を省略すると、privateになる。
例えば、リスト1・7行目のInnerClassのアクセス修飾子publicを削除すると、OuterClass外からInnerClassにアクセスできなくなり、25、26行目でエラーとなる。
内部クラスと外部クラス間のメンバーへのアクセス
親は子に隠し事をしない。
内部クラスからその外側のクラスのメンバーへは、たとえprivate宣言されていてもアクセス可能である。
しかし、逆に、外側クラスからは内部のクラスのメンバーのprivateメンバーへはアクセスできない。
以下のその例を示す。
リスト5
20行目,21行目の変数をprivateに変更するとエラーになってしまう。Javaとの違い
C#の内部クラスは、インスタンスメンバー,クラスの静的メンバーの区別はなく、常に、javaで言うクラスの静的メンバーとして宣言された内部クラス(staticの付いた内部クラス)に相当する。C#では、Javaのようにメソッド内にクラスを定義する事はできない。(Javaで言うローカルクラスは存在しない)
Javaでは、GUIのイベントリスナーの定義にローカルクラスがよく使われるが、C#ではイベントの処理にdelegateを使えるので不自由する事は無い。
Javaでは、インターフェース内部にクラスを定義できるが、C#ではできない。
余談ではあるが、ソースファイル名とトップレベルクラスのクラス名が一致していなくても、C#ではエラーにならない。
Javaでは、内部クラスと外部クラス間のメンバーへのアクセスは自由であるが、c#では内部クラスから外部クラスへは自由であるが逆は制限がある。
総じて、C#の方が、Javaの内部クラスの機能の中から、あっても意味のない(?)部分を削除して、シンプルでわかり易い仕様になっているように思う。
だだ、ローカルクラスについては、C#にもあってもいいのではと思う。
Javaの内部クラスについてはネストした型-内部クラス(インナークラス)(1) - 愚鈍人を参照。
参考URL