2017-10-19 57 views
1

假設我有以下函數定義。Kotlin中任何類型和泛型的區別

fun<T> parse(a: Any): T = when (a) { 
    is String -> a 
    else -> false 
} 

我猜想它應該是有效的。然而,IntelliJ IDEA的棉短絨顯示類型不匹配錯誤

Linter error

話雖這麼說,我想我的解析函數的返回類型更改爲任何,對不對?那麼,在Kotlin中使用Any類型和泛型之間有什麼區別?在哪些情況下應該使用每一種?

我讀過以下question,但根本不瞭解Kotlin的星形投影,因爲我很新。

+1

這個Java的答案可能會幫助你https://stackoverflow.com/questions/5207115/java-generics-t-vs-object – zsmb13

+0

你找到了答案? – s1m0nw1

回答

1

我猜應該是有效

爲什麼它會是什麼?您在一個分支中返回String,而在另一個分支中返回Boolean。因此,整個when表達式的常見類型是Any,這就是編譯器(和IDEA)所說的「找到」。你的代碼也說它應該是T(這是「必需的」)。

您的通用方法應適用於任何T,例如,對於Int,但Any不是Int的子類型,因此代碼無效。

那麼,在Kotlin中使用任何類型和泛型之間有什麼區別?

這就好比問「使用數字和文件有什麼區別」:他們沒有太多共同之處。您可以使用泛型編寫代碼,它可以與所有類型的工作(或所有類型滿足某些約束);當您想要特定類型Any時,您使用Any

1

您的返回類型定義爲T,但沒有任何內容確保Ta:Any有關。 T可能比Any更具限制性,在這種情況下,您無法返回布爾值或您爲a提供的任何內容。

下面的工作,通過改變從T返回類型Any

fun<T> parse(a: Any): Any = when (a) { 
    is String -> a 
    else -> false 
} 

任何替代選項,如果你真的想返回類型T:

inline fun<reified T> parse(a: Any): T? = when (a) { 
    is T -> a 
    else -> null 
} 
0

您的例子不使用T,因此無論如何都是無用的。

想一想:作爲一個客戶,你把某些東西放入一個函數中,例如一個XML-ByteArray,該函數應該解析爲一個Object。調用你不想讓它返回的函數Any(Casting sucks),但希望函數返回解析對象的類型。這可以實現與仿製藥:

fun <T> parse(xml: ByteArray): T { 
    val ctx: JAXBContext = JAXBContext.newInstance() 
    val any = ctx.createUnmarshaller().unmarshal(ByteArrayInputStream(xml)) 
    return any as T 
} 

val int = parse<Int>("123".toByteArray()) 
val string = parse<String>("123".toByteArray()) 

看看方法調用:你告訴泛型什麼類型是預期返回。代碼沒用,只能給你一個泛型的想法。