[英]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.