Kotlin

时间:2017-10-19 17:37:32

标签: kotlin

假设我有以下函数定义。

fun<T> parse(a: Any): T = when (a) {
    is String -> a
    else -> false
}
我猜这应该是有效的。但是,IntelliJ IDEA linter显示类型不匹配错误

Linter error

话虽如此,我会将我的解析函数的返回类型更改为Any,对吧?那么,在Kotlin中使用Any类型和Generics有什么区别?在哪些情况下应该使用这些?

我确实阅读了以下question,但由于我很新的事实,我对Kotlin中的明星投影一无所知。

3 个答案:

答案 0 :(得分:3)

您定义为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
}

答案 1 :(得分:1)

您的示例不使用T,因此无论如何都要将其设为通用。

想一想:作为客户,你将某些东西放入一个函数中,例如一个XML - ByteArray,该函数应该解析为Object。调用你不希望它返回的函数Any(Casting糟透了)但希望函数返回解析对象的类型。这可以通过泛型来实现:

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())

查看方法调用:您告诉泛型预期返回什么类型。代码没有用,只能让你了解泛型。

答案 2 :(得分:1)

  

我猜这应该是有效的

为什么会这样?您在一个分支中返回String,在另一个分支中返回Boolean。因此,整个when表达式的通用类型是Any,而编译器(和IDEA)所说的是&#34;找到&#34;。您的代码还说它应该是T(这是&#34;必需&#34;)。

您的通用方法适用于任何T,例如对于Int,但Any不是Int的子类型,因此代码无效。

  

那么,在Kotlin中使用Any类型和Generics有什么区别?

这就像询问&#34;使用数字和文件之间有什么区别&#34;:它们首先没有多少共同之处。您使用泛型来编写可以使用所有类型T的代码(或者满足某些约束的所有类型);如果需要特定类型Any,请使用Any