簡體   English   中英

靜態通用接口實現

[英]Static generic interface implementation

我有一個簡單的界面:

interface Predicate<T> {

boolean accepts(T in);

}

現在,我還要提供以下形式:

interface Predicate<T> {

public static Predicate<T> ALL = new Predicate<T>(){ ... }

boolean accepts(T in);

}

上述形式不合法。 有沒有一種方法可以提供將要鍵入的通用實現,即在多個上下文中我可以說Predicate.ALL ,有點像Collections.EMPTY_SET

更新:我的意思是接口...

您可以像Collections.emptySet()一樣使用類型推斷(請注意, Collections.EMPTY_SET不使用泛型)。

來自Collections

public static final Set EMPTY_SET = new EmptySet();

public static final <T> Set<T> emptySet() {
  return (Set<T>) EMPTY_SET;
}

您可以像這樣模仿它:

public static Predicate ALL = new Predicate(){ ... }   

public static final <T> Predicate<T> all() {
  return (Predicate<T>) ALL;
}

您只需要用ALL聲明中有意義的內容替換<T> 或完全刪除-注意, Collections.EMPTY_SET的類型為Set ,而不是Set<T>

首先,您的簡單類無效,因為accepts沒有實現,也不是抽象的。 假設您要使它抽象,以便實際謂詞是覆蓋它的派生類。 那么ALL謂詞總是返回true。 但是您不能將其設置為靜態字段,因為靜態字段無法引用type參數。

public abstract class Predicate<T> {
  public abstract boolean accepts(T in);

  public static <T> Predicate<T> all() {
    return new Predicate<T> { boolean accepts(T in) { return true; } };
  }
}

有兩種方法可以實現ALL謂詞:

public interface Predicate<T> {
    public static final Predicate<Object> ALL = new Predicate<Object> {
        @Override public boolean accepts(Object in) { return true; }
    }
    boolean accepts(T in);
}

您在此處聲明一個具體的類字段(一個常量),因此必須對類型變量T使用具體的替換。由於您對類型不感興趣,因此使用了所有對象的超類型:java.lang.Object。

此實現將使編譯器不產生任何警告,這是一個很好的起點。 但是,您有一些困難。 考慮以下代碼:

public class PredicateTester {
    public static void main(String[] args) {
        test1(Predicate.ALL, "some string"); // compiler error
        test2(Predicate.ALL, "some string");
    }
    public static void test1(Predicate<String> pred, String in) {
        System.out.println(pred.accepts(in) ? "pass" : "fail");
    }
    public static void test2(Predicate<? super String> pred, String in) {
        System.out.println(pred.accepts(in) ? "pass" : "fail");
    }
}

盡管test1和test2都是有效方法(並且可以正常編譯),但對方法test1的調用將不會編譯。 簡而言之:Predicate <Object>不是Predicate <String>。

結論:在設計將謂詞作為參數的方法時,必須記住PECS(生產者擴展,消費者超級)。

另一個選擇是根本不提供類型:

public interface Predicate<T> {
    @SuppressWarnings("rawtypes")
    public static final Predicate ALL = new Predicate {
        @Override public boolean accepts(Object in) { return true; }
    }
    boolean accepts(T in);
}

通過該實現,上述類PredicateTester可以正常編譯。 因此,這是要走的路。

按照您編寫的形式,您需要它是抽象的,因為您沒有提供accepts方法的實現。

abstract class Predicate<T> {

    abstract boolean accepts(T in);

}

如果您隨后想要提供多用途“ accept any”謂詞,則可以這樣進行:

public static Predicate ALL = new Predicate(){
    @Override
    boolean accepts(Object in) {
        return true;
    }
};

@SuppressWarnings("unchecked")
static final <T> Predicate<T> all(){ return (Predicate<T>)ALL;}

這模仿了Collections.EMPTY_SET和Collections.emptySet()的工作方式。

請注意,Collections.EMPTY_SET(和Predicate.ALL)不是類型安全的,但是Collections.emptySet()(和Predicate.all())將推斷要分配給它們的類型。

暫無
暫無

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

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