Sobes.tech
Middle

Kako raditi sa generičkim tipovima u Kotlinu?

sobes.tech АИ

Одговор од АИ

Generički tipovi u Kotlinu omogućavaju kreiranje klasa, interfejsa i funkcija koje rade sa podacima različitih tipova, a pritom održavaju sigurnost tipova tokom vremena kompilacije.

Osnovni pojmovi i načini rada:

  • Deklaracija generičkih klasa i interfejsa:
    class Box<T>(val item: T) // Generička klasa sa parametrima tipa T
    interface MyList<E> { // Generički interfejs sa parametrima tipa E
        fun add(element: E)
        fun get(index: Int): E
    }
    
  • Deklaracija generičkih funkcija:
    fun <T> printAnything(value: T) { // Generička funkcija sa parametrima tipa T
        println(value)
    }
    
  • Kreiranje instanci generičkih tipova:
    val intBox: Box<Int> = Box(123) // Navođenje konkretnog tipa (Int)
    val stringBox = Box("hello") // Kompajler odredjuje tip (String)
    
  • Varijantnost: Omogućava definisanje kako funkcionišu podtipovi sa generičkim tipovima.
    • Kovarijantnost (out): Omogućava korišćenje tipa i njegovih podtipova. Označava se sa out. Primer: List<out Any> može sadržati List<String>. Koristi se za tipove koji proizvode vrednosti (npr. čitanje iz kolekcije).
      interface Producer<out T> { // out T - kovarijantni parametar
           fun produce(): T
      }
      
    • Kontravariantnost (in): Omogućava korišćenje tipa i njegovih nadtipova. Označava se sa in. Primer: Comparator<in String> može raditi sa Comparator<Any>. Koristi se za tipove koji konzumiraju vrednosti (npr. zapis u kolekciju).
      interface Consumer<in T> { // in T - kontravariantni parametar
          fun consume(value: T)
      }
      
    • Invarijantnost: Tip u generičkom parametru mora biti tačno isti. Ovo je podrazumevano ponašanje.
  • Ograničenja tipova (where): Omogućava ograničavanje tipa parametra tako da implementira određene interfejse ili nasleđuje od određene klase.
    fun <T : Comparable<T>> max(a: T, b: T): T { // T mora implementirati Comparable
        return if (a > b) a else b
    }
    
    fun <T> process(item: T) where T : Runnable, T : Comparable<T> {
        item.run()
        // ... koristimo poređenje
    }
    
  • Zvezdasta (star) projekcija (*): Koristi se kada nisu važni konkretni argumenti tipa. Slično <?> u Javi.
    fun printList(list: List<*>) { // Može primiti listu bilo kog tipa
         for (item in list) {
             println(item)
        }
    }
    

Generički tipovi u Kotlinu koriste brisanje tipova (type erasure), kao i u Javi. Informacije o konkretnim tipovima parametara gube se tokom izvršavanja. Za rad sa tipovima tokom izvršavanja koriste se reified tipovi.

  • Reified tipovi (reified): Dostupni su samo za inline funkcije. Omogućavaju očuvanje informacija o tipu parametra tokom izvršavanja.
    inline fun <reified T> checkType(value: Any) { // T - reified tip
        if (value is T) {
            println("Value is of type T")
        } else {
            println("Value is not of type T")
        }
    }