簡體   English   中英

子類不匹配通用通配符捕獲

[英]Subclass not matching generic wildcard capture

我有以下示例類表示我遇到的情況:

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

我認為 Event 是 AttributeProvider 類型,因此它應該匹配“?擴展 AttributeProvider”。
這個錯誤的原因是什么?

在這種情況下不能使用通配符。 您需要確切地知道列表中的對象類型,以便插入並再次將其取出。

您可以選擇: List<CompletablePredicate<IDProvider>> filters = new ArrayList<>(); 或者在這種情況下: List<IDFilter> filters = new ArrayList<>();


OP 添加更多信息后編輯。 我想出了以下解決方案。 我刪除了 CompletablePredicate 形式的類型參數,而是給了它一個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));
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM