Sobes.tech
Middle

Jak pracovat s generickými typy v Kotlinu?

sobes.tech AI

Odpověď od AI

Generické typy v Kotlinu umožňují vytvářet třídy, rozhraní a funkce, které pracují s daty různých typů, přičemž zachovávají typovou bezpečnost během kompilace.

Hlavní pojmy a způsoby práce:

  • Deklarace generických tříd a rozhraní:
    class Box<T>(val item: T) // Generická třída s parametrem typu T
    interface MyList<E> { // Generické rozhraní s parametrem typu E
        fun add(element: E)
        fun get(index: Int): E
    }
    
  • Deklarace generických funkcí:
    fun <T> printAnything(value: T) { // Generická funkce s parametrem typu T
        println(value)
    }
    
  • Vytváření instancí generických typů:
    val intBox: Box<Int> = Box(123) // Určení konkrétního typu (Int)
    val stringBox = Box("hello") // Kompilátor odvodí typ (String)
    
  • Variabilita: Umožňuje určit, jak fungují podtypy s generickými typy.
    • Kovarience (out): Umožňuje používat typ a jeho podtypy. Označuje se out. Příklad: List<out Any> může obsahovat List<String>. Používá se pro typy, které produkují hodnoty (například čtení z kolekce).
      interface Producer<out T> { // out T - kovariantní parametr
           fun produce(): T
      }
      
    • Kontravarianta (in): Umožňuje používat typ a jeho nadtypy. Označuje se in. Příklad: Comparator<in String> může pracovat s Comparator<Any>. Používá se pro typy, které spotřebovávají hodnoty (například zápis do kolekce).
      interface Consumer<in T> { // in T - kontravariantní parametr
          fun consume(value: T)
      }
      
    • Invarianta: Typ v generickém parametru musí být přesně stejný. Toto je výchozí chování.
  • Omezení typů (where): Umožňuje omezit typ parametru tak, aby implementoval určité rozhraní nebo dědil z určité třídy.
    fun <T : Comparable<T>> max(a: T, b: T): T { // T musí implementovat Comparable
        return if (a > b) a else b
    }
    
    fun <T> process(item: T) where T : Runnable, T : Comparable<T> {
        item.run()
        // ... používání srovnatelnosti
    }
    
  • Hvězdička (star) projekce (*): Používá se, když nejsou důležité konkrétní argumenty typu. Podobně jako <?> v Javě.
    fun printList(list: List<*>) { // Přijímá seznam jakéhokoliv typu
         for (item in list) {
             println(item)
         }
    }
    

Generické typy v Kotlinu používají ztrátu typu (type erasure), stejně jako v Javě. Informace o konkrétních typech parametrů se ztrácí během běhu. Pro práci s typy během běhu se používají reified typy.

  • Reified typy (reified): Jsou dostupné pouze pro inline funkce. Umožňují zachovat informace o typu parametru během běhu.
    inline fun <reified T> checkType(value: Any) { // T - reified typ
        if (value is T) {
            println("Value is of type T")
        } else {
            println("Value is not of type T")
        }
    }