Kotlin Generic Functions
A generic function works with a type that the caller chooses. One definition holds the logic and each call picks the type that fills its type parameter.
The type follows the arguments
firstOf works for a list of numbers and a list of words. The compiler infers T from the list passed to each call.
fun <T> firstOf(items: List<T>): T {
return items[0]
}
fun main() {
println(firstOf(listOf(3, 5, 7)))
println(firstOf(listOf("sun", "moon")))
}An explicit type argument
The call writes its type in angle brackets after the function name. Both calls build a list that holds the same value twice.
fun <T> twice(value: T): List<T> {
return listOf(value, value)
}
fun main() {
println(twice<String>("hi"))
println(twice<Int>(4))
}Two type parameters with a transform
T names the input type and R names the result type. The transform lambda turns a value of type T into a value of type R.
fun <T, R> convert(value: T, transform: (T) -> R): R {
return transform(value)
}
fun main() {
println(convert(5) { it * 2 })
println(convert("abc") { it.length })
}A generic extension function
The extension adds a method to List with its own type parameter. The method reads the second item or gives null when the list is too short.
fun <T> List<T>.secondOrNull(): T? {
return if (size >= 2) this[1] else null
}
fun main() {
println(listOf(10, 20, 30).secondOrNull())
println(listOf("one").secondOrNull())
}Example
fun <T> middle(items: List<T>): T {
return items[items.size / 2]
}
fun main() {
println(middle(listOf(1, 2, 3, 4, 5)))
println(middle(listOf("a", "b", "c")))
println(middle(listOf(2.5, 1.5)))
}Key points
- A type parameter sits in angle brackets before the function name.
- The compiler can infer the type parameter from the arguments of a call.
- A call can also write its type argument in angle brackets.
- A function can hold two type parameters and use both in its shape.
- A generic extension function adds a generic method to an existing type.
In this example, middle reads the item at the middle position of a list. The first call passes whole numbers and prints 3. The second call passes words and prints b. The last call passes decimal numbers and prints 1.5.
Note
The body of a generic function uses the type parameter like a normal type name.
Try it Yourself
Edit the code, then press Run.
Running is simulated ยท Kotlin Playground
Exercise
A generic function is declared as fun <T> head(items: List<T>): T and called with a list of words. What does T stand for in that call?