1. ホーム
  2. java

[解決済み] メソッドの戻り値の型を汎用的にするにはどうすればよいですか?

2022-03-15 13:33:51

質問

この例(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 ? あるいは、少なくともダミーインスタンスの代わりに、その型のクラスを渡すことによって。
ジェネリックはコンパイル時の型チェックのためと理解していますが、回避策はあるのでしょうか?

解決方法は?

を定義することができます。 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();

このコードには、コンパイラの警告を発生させないという利点があります。もちろん、これはGeneric以前のキャスティングのバージョンを更新したに過ぎず、安全性を追加するものではありません。