Kotlin泛型語法中的歧義性
class C {n public static <A> void f() {}n}n
我們需要這樣來調用:
C.<String>f();n
這樣的寫法讓很多人感到不符合習慣。而在Kotlin中,我們需要這樣調用:
C.f<String>()n
相比較而言,下面的寫法可能更符合大多數人的習慣。不過相對來說,這樣做也引入了Java泛型語法想要避免的歧義性問題。考慮下面的一段代碼:
class C {nval f: Int = 0n fun <T1, T2> f(i: Int): Int {nreturn in }n}nnfun f(b1: Boolean, b2: Boolean): Unit {nprintln("f(Boolean, Boolean)")n}nnfun f(i: Int): Unit {nprintln("f(Int)")n}nnfun <A, B> test() {nval A = 0n val B = 0nn val a = C()nval c = 0nn f(a.f<A, B>(c))n}nnfun main(args: Array<String>): Unit {ntest<Int, Int>()n}n
這樣的一段代碼會列印出什麼呢?對於這裡來說,很明顯能看出會列印"f(Int)"。但是實際上,這個結論並沒有這麼明顯。我們稍微把對於f的調用變換一下形式,加入幾個空格,從
f(a.f<A, B>(c))n
改為
f(a.f < A, B > (c))n
我們發現,a.f<A, B>(c)可能是一個泛型方法的調用,也有可能是比較a.f和A,以及B和c。而這種情況正是我們在Java中想要避免的歧義性。
而對於Kotlin編譯器來說,在這種情況下,<>總是會被解析為泛型方法的調用,而不是比較操作符。所以:
f((a.f)< A, B > (c))n
也會被當做獲取a的f屬性,然後試圖調用這個屬性的帶一個泛型參數的invoke方法。甚至這樣
f((a.f)< A, B > c)n
也會被解析為泛型方法調用而出錯
如果我們真的需要列印出"f(Boolean, Boolean)",我們需要用括弧把兩個參數中至少一個括起來:
f(a.f < A, (B > c)) //或者nf((a.f < A), B > c)n
推薦閱讀:
※廢文(一)
※開源文檔翻譯的質量保障實踐
※Kotlin雜談(一) - 高等函數(Curry + 閉包)
TAG:Kotlin |