Generic methods are methods that work on a variety of different type arguments. Some concrete examples of generic methods found in the Kotlin standard library are listOf(), setOf() mapOf(), with(), apply(), etc. All of these methods are compatible with any type of variable and work correctly for each type. A generic method promotes code reuse because a method can be written with a variable type argument that is later substituted with a real type by the compiler.
It’s very easy to write our own generic methods. We need only declare our type arguments inside of angle brackets after the fun keyword. Here is an example of a method that fills a MutableList with a value.
/** * Generic method that fills a MutableList with a value. The type argument is declared * as T which is later substituted with real types by the compiler. */ fun <T> fillList(list : MutableList<T>, value : T, length : Int){ for (i in 0..length){ list.add(value) } }
Our fill list isn’t anything fancy, but it is very powerful. The fillList() function is compatible with any type of variable because it uses a generic type, T, as a type argument. Later on, the Kotlin compiler will substitute T with Int, String, or any other type that we need for our purposes.
It is worthwhile to note that all of the typed parameters in fillList() are the same type. In other words, the list variable and the value variable both have to be the same type of argument. We are not allowed to pass in a MutableList<String> along with a value of Int. That would result in a compiler error. If we need multiple type arguments, we need to declare them inside of the angle brackets found after the fun keyword.
We can use our fillList() function like any other function when ready. Here is an example of using our function.
package ch6.genericmethods /** * Generic method that fills a MutableList with a value. The type argument is declared * as T which is later substituted with real types by the compiler. */ fun <T> fillList(list : MutableList<T>, value : T, length : Int){ for (i in 0..length){ list.add(value) } } fun main(args : Array<String>){ val intList = mutableListOf<Int>() val stringList = mutableListOf<String>() fillList(intList, 100, 5) fillList(stringList, "Bob", 5) //fillList(intList, "Bob", 5) Not OK! intList is MutableList<Int> while Bob is a String println(intList) println(stringList) }
When run, this program outputs the following.
[100, 100, 100, 100, 100, 100] [Bob, Bob, Bob, Bob, Bob, Bob]