子类与泛型通配符捕获不匹配

dldeef67  于 2021-08-25  发布在  Java
关注(0)|答案(1)|浏览(331)

我有以下示例类,说明我遇到的情况:

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.function.Function;

class Scratch {

interface CompletablePredicate<T> extends Function<T, CompletionStage<Boolean>> {
}

interface AttributeProvider{}

interface IDProvider extends AttributeProvider {
    String getID();
}

interface TypeProvider extends AttributeProvider {
    String getType();
}

static class Event implements IDProvider, TypeProvider{

    @Override
    public String getID() {
        return "123";
    }

    @Override
    public String getType() {
        return "foo";
    }
}

static class IDFilter implements CompletablePredicate<IDProvider> {

    @Override
    public CompletionStage<Boolean> apply(IDProvider idProvider) {
         String id = idProvider.getID();
         boolean res = id.equals("123");
         return CompletableFuture.completedFuture(res);
    }
}

static class TypeFilter implements CompletablePredicate<TypeProvider> {

    @Override
    public CompletionStage<Boolean> apply(TypeProvider typeProvider) {
        String type = typeProvider.getType();
        boolean res = type.equals("foo");
        return CompletableFuture.completedFuture(res);
    }
}

public static void main(String[] args) {
    List<CompletablePredicate<? extends AttributeProvider>> filters = new ArrayList<>();
    filters.add(new IDFilter());
    filters.add(new TypeFilter());
    Event event = new Event();
    filters.stream().forEach(f -> f.apply(event)); <- failing here
}

}
正如所强调的,它无法在中编译 f.apply(event) 有误:

Error:(40, 47) incompatible types: Scratch.Event cannot be converted to capture#1 of 
? extends Scratch.AttributeProvider

我认为事件属于attributeprovider类型,因此它应该匹配“?扩展属性提供者”。
这个错误的原因是什么?

kjthegm6

kjthegm61#

在这种情况下,不可能使用通配符。您需要确切地知道列表中的对象类型,以便插入并再次取出它。
您可以选择: List<CompletablePredicate<IDProvider>> filters = new ArrayList<>(); 或者在这种情况下: List<IDFilter> filters = new ArrayList<>(); 操作后编辑添加了更多信息。我提出了以下解决方案。我删除了类型参数formcompletablepredicate,而是给它一个 supports 方法。其思想是该方法检查参数的类型是否正确。然后,在将事件应用于列表中的所有项目之前,我首先过滤该列表,因此我确信所有剩余元素都支持它。

interface CompletablePredicate extends Function<AttributeProvider, CompletionStage<Boolean>> {
        boolean supports(AttributeProvider provider);
    }

    interface AttributeProvider { }

    interface IDProvider extends AttributeProvider {
        String getID();
    }

    interface TypeProvider extends AttributeProvider {
        String getType();
    }

    static class Event implements IDProvider, TypeProvider {
        @Override
        public String getID() {
            return "123";
        }

        @Override
        public String getType() {
            return "foo";
        }
    }

    static class IDFilter implements CompletablePredicate {
        @Override
        public boolean supports(AttributeProvider provider) {
            return provider instanceof IDProvider;
        }

        @Override
        public CompletionStage<Boolean> apply(AttributeProvider idProvider) {
            String id = ((IDProvider) idProvider).getID();
            boolean res = id.equals("123");
            return CompletableFuture.completedFuture(res);
        }
    }

    static class TypeFilter implements CompletablePredicate {
        @Override
        public boolean supports(AttributeProvider provider) {
            return provider instanceof TypeProvider;
        }

        @Override
        public CompletionStage<Boolean> apply(AttributeProvider typeProvider) {
            String type = ((TypeProvider) typeProvider).getType();
            boolean res = type.equals("foo");
            return CompletableFuture.completedFuture(res);
        }
    }

    public static void main(String[] args) {
        List<CompletablePredicate> filters = new ArrayList<>();

        filters.add(new IDFilter());
        filters.add(new TypeFilter());

        Event event = new Event();

        filters.stream()
            .filter(f -> f.supports(event))
            .forEach(f -> f.apply(event));
    }

相关问题