Sobes.tech
Middle

Hogyan dolgozzunk generikus típusokkal Kotlinben?

sobes.tech MI

Válasz az MI-től

A Kotlin generikus típusai lehetővé teszik osztályok, interfészek és függvények létrehozását, amelyek különböző típusú adatokkal működnek, miközben típusbiztonságot tartanak fenn fordítás közben.

Fő fogalmak és működési módok:

  • Általános osztályok és interfészek deklarálása:
    class Box<T>(val item: T) // Általános osztály T típusparaméterrel
    interface MyList<E> { // Általános interfész E típusparaméterrel
        fun add(element: E)
        fun get(index: Int): E
    }
    
  • Általános függvények deklarálása:
    fun <T> printAnything(value: T) { // Általános függvény T típusparaméterrel
        println(value)
    }
    
  • Általános típuspéldányok létrehozása:
    val intBox: Box<Int> = Box(123) // Konkrét típus megadása (Int)
    val stringBox = Box("hello") // A fordító a típusát kiírja (String)
    
  • Változatosság: Lehetővé teszi a típusok és azok al-típusainak működésének meghatározását.
    • Kovariancia (out): Lehetővé teszi a típus és al-típusainak használatát. out-ként jelöljük. Példa: List<out Any> tartalmazhat List<String>-et. Olyan típusokra használják, amelyek értékeket termelnek (pl. olvasás gyűjteményből).
      interface Producer<out T> { // out T - kovariáns típusparaméter
           fun produce(): T
      }
      
    • Contravariancia (in): Lehetővé teszi a típus és föl-típusainak használatát. in-ként jelöljük. Példa: Comparator<in String> működhet Comparator<Any>-vel. Olyan típusokra használják, amelyek értékeket fogyasztanak (pl. írás gyűjteménybe).
      interface Consumer<in T> { // in T - kontravariáns típusparaméter
          fun consume(value: T)
      }
      
    • Invariancia: A generikus típusnak pontosan ugyanolyannak kell lennie. Ez az alapértelmezett viselkedés.
  • Típuskorlátozások (where): Lehetővé teszi a típus paraméterének korlátozását, hogy bizonyos interfészeket valósítson meg vagy egy adott osztályból örököljön.
    fun <T : Comparable<T>> max(a: T, b: T): T { // T-nek implementálnia kell a Comparable-t
        return if (a > b) a else b
    }
    
    fun <T> process(item: T) where T : Runnable, T : Comparable<T> {
        item.run()
        // ... összehasonlítás használata
    }
    
  • Csillag (star) vetítés (*): Akkor használjuk, amikor nem fontosak a típus konkrét argumentumai. Hasonló a Java <?>-hez.
    fun printList(list: List<*>) { // Bármilyen típusú lista elfogadható
         for (item in list) {
             println(item)
         }
    }
    

A Kotlin generikus típusai típus elmosódást (type erasure) használnak, mint a Java. A konkrét típusparaméterek információja elveszik futás közben. A típusokkal való munka során reified típusokat használnak.

  • Reified típusok (reified): Csak inline függvényekben érhetők el. Lehetővé teszik a típusinformációk megőrzését futás közben.
    inline fun <reified T> checkType(value: Any) { // T - reified típus
        if (value is T) {
            println("Value is of type T")
        } else {
            println("Value is not of type T")
        }
    }