Kotlin中任何类型和泛型之间的区别
假设我有以下的函数定义。
fun<T> parse(a: Any): T = when (a) { is String -> a else -> false }
我猜它应该是有效的。 但是,IntelliJ IDEA linter显示类型不匹配错误
这就是说,我会改变我的解析函数的返回类型为Any,对吗? 那么,在Kotlin中使用任何类型和泛型有什么区别呢? 在哪些情况下应该使用每一个?
我读了下面的问题,但根本不了解Kotlin的星空投影,因为我很新。
你的返回类型定义为T
,但是没有什么能保证T
和a: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 }
我猜它应该是有效的
为什么会这样? 你在一个分支中返回一个String
在另一个分支中返回一个Boolean
所以when
表达式是Any
,这是常见的类型,这就是编译器(和IDEA)所说的“被发现”。 你的代码也说它应该是T
(这是“必需的”)。
你的泛型方法应该适用于任何T
,例如Int
,但Any
不是Int
的子类型,所以代码是无效的。
那么,在Kotlin中使用任何类型和泛型有什么区别呢?
这就像是问“使用数字和文件有什么区别”:它们没有太多共同之处。 你可以使用泛型来编写可以处理所有类型T
代码(或者所有类型都满足一定的约束条件)。 当你想要特定的类型Any
时,你使用Any
。
你的例子不使用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 the any here? No, Client wants concrete type T return any as T } val int = parse<Int>("123".toByteArray()) val string = parse<String>("123".toByteArray())
看看方法调用:你告诉泛型什么类型是预期返回。 代码是没有用的,只能给你一个泛型的想法。