1.1.50.14. fejezet, Generikusok

Definíció:

class Box<T>(t: T) {
    var value = t
}

Példányosítás:

val box: Box<Int> = Box<Int>(1)

Ha azonban a paraméterek kikövetkeztethetők például a konstruktor argumentumokból, elhagyhatja a típus argumentumokat:

val box = Box(1) // 1 has type Int, so the compiler figures out that it is Box<Int>

In, out

interface Source<out T> {
    fun nextT(): T
}
 
fun demo(strs: Source<String>) {
    val objects: Source<Any> = strs // This is OK, since T is an out-parameter
    // ...
}
interface Comparable<in T> {
    operator fun compareTo(other: T): Int
}
 
fun demo(x: Comparable<Number>) {
    x.compareTo(1.0) // 1.0 has type Double, which is a subtype of Number
    // Thus, you can assign x to a variable of type Comparable<Double>
    val y: Comparable<Double> = x // OK!
}

Generikus függvények

fun <T> singletonList(item: T): List<T> {
    // ...
}
 
fun <T> T.basicToString(): String { // extension function
    // ...
}

Típustörlés

A Kotlin által végzett típusbiztonsági ellenőrzések fordításkor történnek. Futásidőben az általános típusok példányai nem tartalmaznak információt a tényleges típusargumentumaikról. A típusinformáció törlődik.

fun handleStrings(list: MutableList<String>) {
    if (list is ArrayList) {
        // `list` is smart-cast to `ArrayList<String>`
    }
}

Aláhúzásjel operátor típus argumentumokhoz

Az aláhúzásjel operátor típus argumentumokhoz használható. Használatával automatikusan kikövetkeztetheti az argumentum egy típusát, ha más típusok explicit módon meg vannak adva.

abstract class SomeClass<T> {
    abstract fun execute() : T
}
 
class SomeImplementation : SomeClass<String>() {
    override fun execute(): String = "Test"
}
 
class OtherImplementation : SomeClass<Int>() {
    override fun execute(): Int = 42
}
 
object Runner {
    inline fun <reified S: SomeClass<T>, T> run() : T {
        return S::class.java.getDeclaredConstructor().newInstance().execute()
    }
}
 
fun main() {
    // T is inferred as String because SomeImplementation derives from SomeClass<String>
    val s = Runner.run<SomeImplementation, _>()
    assert(s == "Test")
 
    // T is inferred as Int because OtherImplementation derives from SomeClass<Int>
    val n = Runner.run<OtherImplementation, _>()
    assert(n == 42)
}