ジェネリックなインスタンスの
例
java.util.ArrayList の例
public boolean add(E e)
public E get(int index)
複数のメソッド間で型の関連性を表現している
11.
文法のはなし
public class Syntax<T>
implements Iterable<String> {
public <X> void hoge(X x) {
List<X> list = new ArrayList<X>();
list.add(x);
}
@Override
public Iterator<String> iterator() {
return null;
}
}
似て非なる<>を色分けしてみました
12.
3種類の<>
型変数の宣言
class Hoge<T>{}
public <T> void hoge() {}
型変数のバインド
new ArrayList<String>();
class Hoge extends ArrayList<String> {}
Collections.<String>replaceAll(
list, "hoge", "piyo");
パラメータ化された型
( parameterized type )
List<String> list;
<? super ~> の出力制約
ArrayList<? super B> には
B 型を add() できる
ただし get() は Object 型としてしか返せな
い
25.
継承によるバインド
public class StringList
extends ArrayList<String> {}
というクラスを作ると
StringList list = new StringList();
list.add("hoge");
String str = list.get(0);
といったように、型変数のないクラスになる
内部クラスの利用例
public class SampleList<T>extends ArrayList<T> {
@Override
public Iterator<T> iterator() {
return super.iterator();
}
public class SampleIterator
implements Iterator<T> {
// 略
}
}
そもそも内部クラスの使いどころが難しいですが。
37.
new T() したい
「Java のジェネリクスは
new T() ってできないのがクソだよね」
「お前の設計がクソなんじゃないの?」
Factory の実装例
interface HogeFactory<Textends A> {
/** デフォルトコンストラクタ的な */
T newInstance();
}
インスタンスの生成に必要なデータを Factory で制約
public class HogeTemplate {
public <T> T template(HogeFactory<T> factory) {
return factory.newInstance();
}
}
こうすればインスタンスの生成は可能になる、が面倒
41.
妥協例
public <T extendsA> T template(T obj) {
try {
return (T)obj.getClass().newInstance();
} catch (InstantiationException |
IllegalAccessException e) {
throw new RuntimeException(e);
}
}
public <T extends A> T template(Class<T> clazz) {
try {
return (T)clazz.newInstance();
} catch (InstantiationException |
IllegalAccessException e) {
throw new RuntimeException(e);
}
}
再帰での相互参照
二つの型の具象型が、相互に相手の具象型を知っている
class Hoge<H extendsHoge<H, P>,
P extends Piyo<H, P>>
class Piyo<H extends Hoge<H, P>,
P extends Piyo<H, P>>
実装は
class HogeImpl extends Hoge<HogeImpl, PiyoImpl>
class PiyoImpl extends Piyo<HogeImpl, PiyoImpl>
45.
相互再帰+1
汎用型変数 T を追加してみる
classHoge<T, H extends Hoge<T, H, P>,
P extends Piyo<T, H, P>>
class Piyo<T, H extends Hoge<T, H, P>,
P extends Piyo<T, H, P>>
実装クラス
class HogeImpl<T> extends
Hoge<T, HogeImpl<T>, PiyoImpl<T>>
class PiyoImpl<T> extends
Piyo<T, HogeImpl<T>, PiyoImpl<T>>
やりすぎです
46.
内部クラスでグルーピング
二つのクラスを囲うクラスを作って
Hoge と Piyoを内部クラスにすれば…!
public abstract class Outer
<H extends Outer<H, P>.Hoge,
P extends Outer<H, P>.Piyo> {
public abstract class Hoge {
public abstract P getConcretePiyo();
}
public abstract class Piyo {
public abstract H getConcreteHoge();
}
}
やりすぎです