简体   繁体   English

子类不匹配通用通配符捕获

[英]Subclass not matching generic wildcard capture

I have the below sample classes denoting the situation that I am encountering:我有以下示例类表示我遇到的情况:

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
}

} }

As highlighted, its failing to compile in f.apply(event) with error:正如所强调的,它无法在f.apply(event)编译并出现错误:

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

I thought Event is of type AttributeProvider and hence it should match "? extends AttributeProvider".我认为 Event 是 AttributeProvider 类型,因此它应该匹配“?扩展 AttributeProvider”。
What is the reason for this error?这个错误的原因是什么?

Wildcards are not possible in this case.在这种情况下不能使用通配符。 You need to know exactly what type of object is in the list in order to insert it and get it out again.您需要确切地知道列表中的对象类型,以便插入并再次将其取出。

You can choose between: List<CompletablePredicate<IDProvider>> filters = new ArrayList<>();您可以选择: List<CompletablePredicate<IDProvider>> filters = new ArrayList<>(); or in this case: List<IDFilter> filters = new ArrayList<>();或者在这种情况下: List<IDFilter> filters = new ArrayList<>();


Edit after OP added more information. OP 添加更多信息后编辑。 I came up with the following solution.我想出了以下解决方案。 I removed the type parameter form CompletablePredicate, and instead gave it a supports method.我删除了 CompletablePredicate 形式的类型参数,而是给了它一个supports方法。 The idea is that this method checks if the argument is of the correct type.这个想法是这个方法检查参数是否是正确的类型。 Then, before applying the event to all items in the list, I first filter that list, so I'm sure all remaining elements support it.然后,在将事件应用于列表中的所有项目之前,我首先过滤该列表,因此我确定所有剩余元素都支持它。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM