20

Javaのオブジェクトを結合されたジェネリック型にキャストすることは可能ですか?

私は次のような方法を持っています:

public static <T extends Foo & Bar> void doSomething(T object) {
    //do stuff
}

両方のインターフェイス (Foo と Bar) を実装するクラスがある場合、このメソッドを呼び出すことは問題ありません。

問題は、このメソッドを呼び出す必要があるときに、渡す必要のあるオブジェクトを受け取ったjava.lang.Objectときに、コンパイラを満足させるためにキャストする必要があることです。しかし、このキャストを作成する方法がわかりません。

編集:

問題は、次のような関数にあります。

public void problemFunction (Object o) {
  if ( o instanceof Foo && o instanceof Bar) {
      doSomething((Problematic cast) o);
  }
}

}

4

5 に答える 5

13

残念ながら、この状況を満足させるために作成できる法的なキャストはありません。それにキャストできるように、必要なすべてのインターフェースを境界として実装することがわかっている単一のタイプが存在する必要があります。は、目的のために作成したタイプ、または既存のタイプである可能性があります。

interface Baz extends Foo, Bar { }

public void caller(Object w) {
  doSomething((Baz) w);
}

のように、境界を満たす他のタイプがわかっている場合は、それらのタイプをテストし、それらのタイプへのキャストを使用しBazて呼び出すブランチを呼び出し元に含めることができます。doSomethingかわいくないです。

委任を使用Bazして、で必要な範囲を満たす独自のクラスを作成することもできますdoSomething。次に、渡されたオブジェクトをBazクラスのインスタンスでラップし、そのラッパーをに渡しますdoSomething

private static class FooBarAdapter implements Foo, Bar {
  private final Object adaptee;
  FooBarAdapter(Object o) {
    adaptee = (Foo) (Bar) o;
  }
  public int flip() { return ((Foo) adaptee).flip(); }
  public void flop(int x) { ((Foo) adaptee).flop(x); }
  public void blort() { ((Bar) adaptee).blort(); }
}

public void problemFunction (Object o) {
  doSomething(new FooBarAdapter(o));
}
于 2008-11-25T18:06:54.837 に答える
7
public static <T extends Foo & Bar> void doSomething(T object)

これは、問題のオブジェクトに対して複数の操作を実行していることを示しているようです。

オブジェクトに対して実行している目的の操作が、インターフェイス間で分離できるほど十分に明確である場合、それらは独自のメソッドに値するほど十分に明確であると私は主張します。

このコードを再構築して、別のメソッドを呼び出して目的の操作を実行できる可能性があります。これにより、クライアントの観点から操作全体がより明確になる場合があります。

それ以外の:

public void problemFunction (Object o) {
  if (o instanceof Foo && o instanceof Bar) {
      doSomething((Problematic cast) o);
  }
}

あれは。。。になる:

public void problemFunction(Object o) {
  if (o instanceof Foo && o instanceof Bar) {
      fooifySomething((Foo) o);
      baratizeSomething((Bar) o);
  }
}
于 2008-11-25T20:27:40.403 に答える
-1

回避策として、FooとBarを拡張する別のインターフェースFooBarを定義し、クラスにそれを実装させることができます。トップレベルのインターフェースである必要はありません。コードの残りの部分を乱雑にしたり、後付けしたりしたくない場合は、プライベートとして宣言できます。

private interface FooBar extends Foo, Bar {}
public void problemFunction (Object o) {
  if ( o instanceof Foo && o instanceof Bar) {
      doSomething((FooBar) o);
  }
}
于 2008-11-25T18:18:39.727 に答える