Sobes.tech
Middle

Cum să lucrezi cu tipurile generice în Kotlin?

sobes.tech AI

Răspuns de la AI

Tipurile generice în Kotlin permit crearea de clase, interfețe și funcții care lucrează cu date de diferite tipuri, păstrând siguranța tipurilor în timpul compilării.

Concepte principale și moduri de lucru:

  • Declarația de clase și interfețe generice:
    class Box<T>(val item: T) // Clasă generică cu parametru de tip T
    interface MyList<E> { // Interfață generică cu parametru de tip E
        fun add(element: E)
        fun get(index: Int): E
    }
    
  • Declarația de funcții generice:
    fun <T> printAnything(value: T) { // Funcție generică cu parametru de tip T
        println(value)
    }
    
  • Crearea de instanțe ale tipurilor generice:
    val intBox: Box<Int> = Box(123) // Specificarea unui tip concret (Int)
    val stringBox = Box("hello") // Compilatorul deduce tipul (String)
    
  • Variații: Permite definirea modului în care funcționează subtipurile cu tipuri generice.
    • Covarianța (out): Permite utilizarea tipului și a subtipurilor sale. Se indică cu out. Exemplu: List<out Any> poate conține List<String>. Se folosește pentru tipuri care produc valori (de exemplu, citirea din colecții).
      interface Producer<out T> { // out T - parametru covariant
           fun produce(): T
      }
      
    • Contravarianța (in): Permite utilizarea tipului și a supertipurilor sale. Se indică cu in. Exemplu: Comparator<in String> poate lucra cu Comparator<Any>. Se folosește pentru tipuri care consumă valori (de exemplu, scrierea în colecții).
      interface Consumer<in T> { // in T - parametru contravariant
          fun consume(value: T)
      }
      
    • Invarianța: Tipul din parametrul generic trebuie să fie exact același. Aceasta este comportamentul implicit.
  • Restricții de tipuri (where): Permite limitarea tipului parametrului pentru a implementa anumite interfețe sau a moșteni o anumită clasă.
    fun <T : Comparable<T>> max(a: T, b: T): T { // T trebuie să implementeze Comparable
        return if (a > b) a else b
    }
    
    fun <T> process(item: T) where T : Runnable, T : Comparable<T> {
        item.run()
        // ... utilizarea comparabilității
    }
    
  • Proiecția cu stea (*): Se folosește atunci când nu contează argumentele specifice ale tipului. Similar cu <?> în Java.
    fun printList(list: List<*>) { // Poate accepta o listă de orice tip
         for (item in list) {
             println(item)
         }
    }
    

Tipurile generice în Kotlin utilizează ștergerea tipurilor (type erasure), ca și în Java. Informația despre tipurile specifice se pierde în timpul execuției. Pentru a lucra cu tipuri în timpul execuției, se folosesc tipuri reificate.

  • Tipuri reificate (reified): Disponibile doar pentru funcții inline. Permite păstrarea informației despre tipul parametrului în timpul execuției.
    inline fun <reified T> checkType(value: Any) { // T - tip reificat
        if (value is T) {
            println("Valoarea este de tip T")
        } else {
            println("Valoarea nu este de tip T")
        }
    }