문제

I'm having some trouble with a class that contains a member that uses generics. Consider the following sample classes:

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;
    }
}

I then have the following class that uses a Structure

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
        }
    }
}

By itself, this won't work;

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);
}

This makes sense; StructureImpl<BaseRequest> is not actuall a subclass of StructureImpl<SubRequest>. So, I try modifying the StructureUsingObject to use wildcards:

    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
        }
    }
}

This doesn't work either;

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, that makes sense too, although the autocomplete tooltip doesn't (it states that getDependencies should have (null t) as its arguments). I'm not really sure where to go from here. I can't use a wildcard within the foreach. How can I satisfy the requirement that my StructureUsingObject can accept Structures with subclasses of BaseRequest, but while also being able to call getDependencies with elements from the list?

도움이 되었습니까?

해결책

Adapt your last version to capture the wildcard.

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
    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top