次の例を考えてみましょう (OOP の本ではよくある例です)。
クラスがありAnimal
、各クラスにはAnimal
多くの友達が存在します。また、、など
のサブクラスがあり、、などの特定の動作を追加します。Dog
Duck
Mouse
bark()
quack()
クラスは次のとおりですAnimal
:
public class Animal {
private Map<String,Animal> friends = new HashMap<>();
public void addFriend(String name, Animal animal){
friends.put(name,animal);
}
public Animal callFriend(String name){
return friends.get(name);
}
}
以下は、型キャストを多用したコード スニペットです。
Mouse jerry = new Mouse();
jerry.addFriend("spike", new Dog());
jerry.addFriend("quacker", new Duck());
((Dog) jerry.callFriend("spike")).bark();
((Duck) jerry.callFriend("quacker")).quack();
戻り値の型にジェネリックを使用して型キャストをなくす方法はありますか?
jerry.callFriend("spike").bark();
jerry.callFriend("quacker").quack();
以下は、戻り値の型が、決して使用されないパラメーターとしてメソッドに渡された初期コードです。
public<T extends Animal> T callFriend(String name, T unusedTypeObj){
return (T)friends.get(name);
}
instanceof
追加のパラメータを使用せずに実行時に戻り値の型を判断する方法はありますか? または、少なくともダミーインスタンスの代わりに型のクラスを渡すことによって判断する方法はありますか
? ジェネリックはコンパイル時の型チェック用であることは理解していますが、これに対する回避策はありますか?
ベストアンサー1
次のように定義できますcallFriend
。
public <T extends Animal> T callFriend(String name, Class<T> type) {
return type.cast(friends.get(name));
}
次のように呼び出します。
jerry.callFriend("spike", Dog.class).bark();
jerry.callFriend("quacker", Duck.class).quack();
このコードには、コンパイラー警告が生成されないという利点があります。もちろん、これはジェネリック以前のキャストの更新バージョンにすぎず、追加の安全性は追加されません。