1

次の点を考慮してください。

public class Doer {
   public static void doStuff(A a) {
       System.out.println("a");
   }
   public static void doStuff(B b) {
    System.out.println("b");
   }
}

B が A を拡張する場所

そして、このようなジェネリック クラス:

public class NewClass<T extends A> {
    public void doSomething(T entity) {
        Doer.doStuff(entity);
    }
}

このメソッドを次のように呼び出すと、「a」が出力されます

new NewClass<B>().doSomething(new B());

"b" を印刷するにはどうすればよいですか?

前もって感謝します

編集:汚い解決策は変更することです

Doer.doStuff(entity);

if(entity instanceof B){
    Doer.doStuff((B) entity);
}else {
    Doer.doStuff(entity);
}

しかし、instanceof を使用しないソリューションを探しているので、A を拡張する新しいクラスを作成するときに、追加の if (C instance of A) ... を NewClass に追加する必要はありません。

4

4 に答える 4

2

回答については、次の質問を参照してください。Java ジェネリック / タイプ ディスパッチ 質問Java メソッド ディスパッチは、ジェネリックおよび抽象クラスでどのように機能しますか?

基本的に、次のオプションがあります。

于 2013-07-26T09:09:46.267 に答える
1

Java は、引数の型に基づく動的バインディングを行いません。呼び出される実際のメソッドは、コンパイル時に決定されます。したがって、ジェネリック型の場合Object、パラメーター型としてのメソッドが呼び出されます。

instanceof で型をチェックすることでこれを回避できますが、これを処理する純粋な方法は、ポリモーフィズムを活用し、Double Dispatchを使用することです。ただし、呼び出しクラスと引数クラスを緊密に結合するため、常に選択できるわけではありません。

于 2013-07-26T09:16:59.750 に答える
0

その場合、関数 doSomething はエンティティが A から継承されていると推測するだけなので、エンティティのタイプを実際に決定してキャストする必要があると思います。基本的には、次のことができます。

public void doSomething(T entity) {
    if (entity instanceof B) {
        Doer.doStuff((B) entity);
    }
    else {
        Doer.doStuff(entity);
    }
}
于 2013-07-26T09:10:46.260 に答える
0

NewClass にも 2 つのメソッドが必要です。または、次のようにすることもできます。

public class NewClass<T extends A> {
    public void doSomething(T entity) {
        if(entity instanceof B){
            Doer.doStuff((B)entity);
        }else if(entity instanceof A){
            Doer.doStuff((A)entity);
        }
    }
}
于 2013-07-26T08:57:43.333 に答える