カクテルの楽しみは違う種類のお酒を混ぜ合わせることでまったく新しい味わいが生まれるところでしょうか。
今回のカクテルはジェネリクスと内部クラスのシェークでお届けします。
4種の内部クラスごとに外部クラスの型パラメータの参照の可否が違います。
まずは、staticな内部クラス。
staticな内部クラスは基本的にトップレベルのクラスと同機能で、
外部クラスに対してアクセスレベルに特権がある程度です。
staticな内部クラスでは外部クラスの型パラメータにアクセスできません。
これは、型パラメータがインスタンス毎の情報であるため、
外部クラスのインスタンスとの結びつきを持たないstaticな内部クラスでは当然ともいえます。
public class Hoge<T> {
/** staticな内部クラス */
static class Piyo {
private T field; // Tが不可視なのでエラーとなる
}
}
次はエンクロージング型の内部クラスです。
こちらは外部クラスのインスタンスと結びつきがあるため、
外部クラスの型パラメータをそのまま利用することが出来ます。
public class Hoge<T> {
/** エンクロージング型の内部クラス */
class Piyo {
private T field; // 外部クラスの型パラメータを利用できる
public T getField() {
return this.field;
}
}
public static void main(String[] args) {
// Hogeインスタンスを型パラメータStringで作成
Hoge<String> hoge = new Hoge<String>();
// 内部クラスPiyoのインスタンスを作成
Hoge<String>.Piyo piyo = hoge.new Piyo();
// Hogeのインスタンスの型パラメータを利用しているので
// getField()の返り値はString型になっている
String str = piyo.getField();
}
}
上記ソースの通り、PiyoクラスはnewするときのHogeクラスの型パラメータを引き継ぐので、
hoge.new Piyo();
といようにPiyo型の後ろの部分に型パラメータStringがついていません。
しかし、Piyo型は外部クラスのHoge型とは別に型パラメータを持つこともできます。
public class Hoge<T> {
/** エンクロージング型の内部クラス */
class Piyo<X> {
private T outerType;
private X innerType;
}
public static void main(String[] args) {
// Hogeインスタンスを型パラメータStringで作成
Hoge<String> hoge = new Hoge<String>();
// 内部クラスPiyoのインスタンスを作成
Hoge<String>.Piyo<Integer> piyo = hoge.new Piyo<Integer>();
}
}
Piyo型の型パラメータはPiyo型の後ろに付いているのがわかるでしょうか。
ここで注意点としては、
前回の稿でも取り上げたハイディングが起こることです。
public class Hoge<T> {
/** エンクロージング型の内部クラス */
class Piyo<T> { // ここのTは外部クラスのTのハイディング
}
}
ハイディングがおこるのは内部クラスで宣言する型パラメータの部分です。
extendsやimplements部分の
型パラメータとしては外部クラスの型パラメータを使うことが出来、
これはハイディングを起こしません。ちょっとややこしいですね。
public class Hoge<T> {
/** エンクロージング型の内部クラス */
class Piyo implements Comparable<T> {
@Override
public int compareTo(T o) {
return 0;
}
}
}
ちょっと長くなってきましたので、ここらで次回持ち越しとしましょう。
投稿日時 : 2007年8月10日 20:54