0

ジェネリックを使用するメンバーを含むクラスで問題が発生しています。次のサンプル クラスを検討してください。

class BaseRequest {
    // Content goes here
}

class SubRequest extends BaseRequest {
    // IFace methods go here, etc.
}

// Simple datastructure interface
interface Structure<T> {

    List<T> getElementsList();


    Collection<T> getDependencies(T t);
}

// Simple structure implementation, details unimportant
class StructureImpl<T> implements Structure<T> {

    @Override
    public List<T> getElementsList() {
        // Implementation details not important
        return null;
    }


    @Override
    public Collection<T> getDependencies(T t) {
        // implementation details not important
        return null;
    }
}

次に、構造体を使用する次のクラスがあります

class StructureUsingObject {
    final Structure<BaseRequest> structure;


    public StructureUsingObject(Structure<BaseRequest> structure) {
        this.structure = structure;
    }


    public void foo() {
        for (BaseRequest request : structure.getElementsList()) {
            Collection<BaseRequest> requests = this.structure.getDependencies(request);
            // do things
        }
    }
}

これだけではうまくいきません。

public void foo() {
    StructureImpl<BaseRequest> baseImpl = new StructureImpl<BaseRequest>();
    StructureUsingObject baseStruct = new StructureUsingObject(baseImpl);

    StructureImpl<SubRequest> subImpl = new StructureImpl<SubRequest>();
    // Compile error on this line
    StructureUsingObject subStruct = new StructureUsingObject(subImpl);
}

意味あり; StructureImpl<BaseRequest> は実際には StructureImpl<SubRequest> のサブクラスではありません。そこで、ワイルドカードを使用するように StructureUsingObject を変更してみます。

    class StructureUsingObject {
    final Structure<? extends BaseRequest> structure;


    public StructureUsingObject(Structure<? extends BaseRequest> structure) {
        this.structure = structure;
    }


    public void foo() {
        for (BaseRequest request : structure.getElementsList()) {
            // Compile error on this line
            Collection<BaseRequest> requests = this.structure.getDependencies(request);

            // To clarify, a compile error would happen here as well; the issue isn't with the return type
            this.structure.getDependencies(request);

            // do things
        }
    }
}

これもうまくいきません。

The method getDependencies(capture#4-of ? extends BaseRequest) in the type Structure<capture#4-of ? extends BaseRequest> is not applicable for the arguments (BaseRequest)

OK、それも理にかなっていますが、オートコンプリートのツールチップはそうではありません (getDependencies は引数として (null t) を持つ必要があると述べています)。ここからどこへ行けばいいのかよくわかりません。foreach 内でワイルドカードを使用できません。StructureUsingObject が BaseRequest のサブクラスを持つ構造体を受け入れることができると同時に、リストの要素で getDependencies を呼び出すこともできるという要件を満たすにはどうすればよいですか?

4

1 に答える 1

2

ワイルドカードをキャプチャするように最後のバージョンを調整します。

public void foo() {
    bar(this.structure);
}

private <T extends BaseRequest> void bar(Structure<T> s) {
    for (T request : s.getElementsList()) {
        Collection<T> requests = s.getDependencies(request);

        // do things
    }
}
于 2013-04-12T14:59:39.010 に答える