Kotlin提供了对泛型函数的支持。
一、泛型函数的使用
在声明函数时允许定义一个或多个泛型形参,泛型形参要用尖括号括起来,整体放在fun与函数名之间。格式如下:
fun <T,S> 函数名(形参列表):返回值类型{
//函数体....
}
package test0709
fun <T> copy(from: List<T>, to: MutableList<in T>) {
for (ele in from) {
to.add(ele)
}
}
fun main(args: Array<String>) {
var strList = listOf("Java", "Kotlin")
var objList: MutableList<Any> = mutableListOf(2, 1.2, "Android")
//指定泛型函数的T为String类型
copy<String>(strList, objList)
println(objList)
var intList = listOf(7, 13, 17, 19)
//不显式指定泛型函数的T的类型,系统推断出T为Int类型
copy(intList, objList)
println(objList)
}
输出结果:
[2, 1.2, Android, Java, Kotlin]
[2, 1.2, Android, Java, Kotlin, 7, 13, 17, 19]
声明了泛型函数之后,调用泛型函数时可以在函数名后用尖括号传入实际的类型;也可以在调用泛型函数时不为泛型参数指定实际类型,让系统自动推断出泛型参数的类型。
package test0709
//为泛型形参T扩展方法
fun <T> T.toBookString(): String {
return "《${this.toString()}》"
}
fun main(args: Array<String>) {
val a = 2
//显式指定泛型函数的T为Int类型
println(a.toBookString<Int>())
//不显式指定泛型函数的T的类型,系统推断出T为Double类型
println(3.4.toBookString())
val str = "Kotlin"
//不显式指定泛型函数的T的类型,系统推断出T为String类型
println(str.toBookString())
}
输出结果:
《2》
《3.4》
《Kotlin》
二、具体化类型参数
Kotlin允许在内联函数(使用inline修饰的函数)中使用reified修饰泛型形参,就可以将泛型形参变成一个具体化的类型参数。
val db = listOf("Java", Date(), 103, 2.3, '我')
fun <T> findData(clazz: Class<T>): T? {
for (ele in db) {
if (clazz.isInstance(ele)) {
@Suppress("UNCHECKED_CAST")
return ele as? T
}
}
return null
}
上面代码定义了一个clazz:Class
可以考虑使用reified修饰内联函数的泛型形参,这样可以直接在函数中使用该类型形参,从而避免用户通过函数的参数来传入类型。
//使用reified修饰泛型形参,使之成为具体化的类型参数
inline fun <reified T> findData():T?{
for (ele in db) {
//在函数中直接使用T作为普通类型
if (ele is T) {
return ele
}
}
return null
}
对于使用reified修饰的具体化的类型参数,程序可以在函数体内对该参数使用反射。
inline fun <reified T> membersOf() = T::class.members