2013-04-22 63 views
3

我有一個Predicate<Object>,需要一個等效的Predicate<Animal>逆轉換番石榴預測

Predicate<Animal> provideIsSentientPredicate() { 
    // Won't compile -- cannot convert from Predicate<Object> to Predicate<Animal> 
    return Predicates.instanceOf(Human.class); 
} 

謂詞是逆變,所以轉換Predicate<Object>Predicate<Animal>是安全的。是否有乾淨可讀的方式將Predicate<Object>轉換爲Predicate<Animal>(例如不禁止警告)?

我不想改變我的方法的類型簽名來返回一個Predicate<? super Animal>Predicate<Object>除非有人說服我,是做正確的事。

+0

可選的相關問題:http://stackoverflow.com/questions/7848789/how-to-use-guava-optional-as-naturally-covariant-object – 2013-04-22 17:20:30

+0

「Predicates.instanceOf」的類型絕對是爲了推你要麼返回一個'謂詞<?超級動物>',或者返回'Predicate '並且改變調用者期望'謂詞<?超級動物>'。 – 2013-04-22 17:31:27

+0

@Louis哇!真?那完全不是我的期望!我一直認爲用一個通配符類型來處理客戶端是很粗魯的,所以我從來沒有寫過一個帶有通配符返回類型的方法。通配符返回類型是否被認爲是良好的實踐?我無法回想起Guava源代碼樹中返回通配符類型的任何方法 - 有沒有一種方法? – 2013-04-22 17:57:08

回答

4
Predicate<Animal> provideIsSentientPredicate() 
{ 
    return cast(Predicates.instanceOf(Human.class)); 
} 

static <A, B extends A> Predicate<B> cast(Predicate<A> pa) 
{ 
    @SuppressWarnings("unchecked") 
    Predicate<B> pb = (Predicate)(pa); 
    return pb; 

    // we know it works correctly in practice. 
    // or if you are a theorist, create a wrapper predicate 
    // 
    //  Predicate<B> 
    //   boolean apply(B b) 
    //    return pa.apply(b); 
} 

順便說一句,有沒有理由番石榴不應申報方法

static <T> Predicate<T> instanceOf(Class<?> clazz) 

與其他兄弟姐妹方法一致。

+1

是的,我不明白爲什麼它不是靜態的謂詞 instanceOf(類 clazz)',但番石榴團隊通常有這樣的事情很好(如果微妙)的原因。 Guava在其他靜態工廠方法('Ordering.allEqual()','Ordering.arbitrary()','Ordering.usingToString()')中避免了泛型,而@Louis註釋似乎表明'Predicates.instanceOf()'' s返回類型是故意的。儘管如此,仍然不知道爲什麼。 – 2013-04-22 19:54:57

+2

在回覆我之前的評論時,我猜想最可能的原因是「謂詞 instanceOf(類 clazz)」的方法簽名不是「static」謂詞 instanceOf(類 clazz)'是第二個簽名更多複雜的,難以測試的,難以閱讀的,不太適應的,並且在足夠的情況下不能在第一簽名方面具有優勢來進行切換。但是,如果有比這更深的原因,我真的很好奇聽到它。 – 2013-04-22 20:07:11