5

私はいくつかの提供されたインターフェースを持っています

public interface Finder<S extends Stack<T>,T extends Item> {
    public S find(S s, int a);
}

public interface Stack<T extends Item> {
    Stack<T> getCopy();
}

そして、最初のものを実装するクラス:

public class SimpleFinder<S extends Stack<T>,T extends Item> implements Finder<S,T>{

    public S find(S s, int a){
         S stack = ....;
         ...
         stack = s.getCopy(); \\Error: incompatible types
                              \\       required: S
                              \\       found:    Stack<T>
        .....
        return stack;
    }


}

インターフェースを変更できない場合、実装を可能な限り汎用的に保ちながら、最善の方法は何でしょうか?

編集 インスタンス化を中断できない他のコードがある SimpleFinder<ClassA,ClassB>ため、実装にも2つのジェネリック型が必要です。

4

5 に答える 5

2

インターフェイスを変更することはできないため、ブルート キャストを行うしかありません。

foo.bar()より一般的な議論では、ここで必要なのは「自己型」です。メソッド呼び出しは の静的型を返す必要があると言いたいのfooです。通常、self 型は、メソッドが自分自身を返す流暢な API に必要fooです。あなたの場合、新しいオブジェクトを返したいとします。

Java では、self 型に対する満足のいく答えはありません。1 つのトリックは、 のような自己参照型パラメーターをFoo<T extends Foo<T>>使用することですが、これは非常に見苦しく、サブタイプBarFoo<Bar>. そして、そのトリックはあなたの場合にはまったく役に立ちません。

別のトリックが機能する可能性があります

public interface Stack<T extends Item> {
    <X extends Stack<T>> X getCopy();
}

ここでは、呼び出し元が正確な戻り値の型を提供します。

     S stack = ....;
     ...
     stack = s.getCopy();
     // compiles, because X is inferred to be S

このトリックは、呼び出しサイトを簡素化するのに役立ちます。ただし、ブルート キャストはまだ存在し、 の実装に隠されていますgetCopy()。このトリックは危険であり、発信者は自分が何をしているのかを知っている必要があります。個人的にはやりません。強制呼び出し元がキャストを行う方が良いです。

于 2013-06-12T20:45:38.537 に答える
0

あなたの型Sは のサブタイプですStack<T>が、コピー メソッドはのサブタイプである可能性がある にアップキャストしています。コピーの結果をキャストする必要がありますStack<T>Stack<T>S

于 2013-06-12T19:53:27.967 に答える
0
public class SimpleFinder<S extends Stack<T>,T extends Item> implements Finder<S,T>{
    public S find(S s, int a){
        Stack<T> stack = ....;
        ...
        stack = s.getCopy();
        .....
        return (S) stack;
    }
}

動作するはずです。stack はgetCopy() の戻り値の型と一致Stack<T>しない必要があることに注意してください。タイプは extends であるため、OK であるSと予想されますが、これを実装することは、私が観察している動作です。SStack<T>

于 2013-06-12T19:48:34.780 に答える