Sobes.tech
Senior

Co wiesz o zasadzie projekcji gwiazdowej?

sobes.tech AI

Odpowiedź od AI

Zasada projekcji gwiazdkowej (Star Projection) w Kotlinie to bezpieczny sposób korzystania z generyków, gdy nie jest ważny konkretny typ argumentu, ale trzeba zapewnić bezpieczeństwo typów.

Stosuje się ją w następujących przypadkach:

  • * : Odpowiada Any?. Oznacza, że typ argumentu jest nieznany i nie ma informacji o jego granicach. Można czytać tylko elementy będące instancjami Any?, i nie można niczego zapisywać, oprócz null.

    // Odczyt z listy o nieznanym typie
    fun readFromList(list: List<*>) {
        val item: Any? = list.firstOrNull()
        // Można bezpiecznie odczytać jako Any?
    }
    
  • in * : Odpowiada in Nothing. Używane dla typów kowariantnych (out), gdy nie jest ważny konkretny typ dolny. Można tylko dodawać elementy (typ Nothing, co jest niemożliwe), ale nie można odczytywać.

    // Niemożliwe bezpieczne dodawanie elementów do listy kowariantnej
    fun addToList(list: MutableList<out *>) {
        // list.add(...) // Nie skompiluje się
    }
    
  • out * : Odpowiada out Any?. Używane dla typów kontrawariantnych (in), gdy nie jest ważny konkretny typ górny. Można tylko odczytywać elementy (jak Any?), ale nie można zapisywać.

    // Odczyt z comparatora z typem kontrawariantnym
    fun compare(comparator: Comparator<in *>) {
        // Można wywołać metody, które NIE przyjmują typu T
        // comparator.compare(obj1, obj2) // Nie skompiluje się bez konwersji typu
    }
    

Głównym celem projekcji gwiazdkowych jest bezpieczna interakcja z klasami i funkcjami generycznymi, gdy pełny typ argumentu jest nieznany lub nieistotny dla bieżącej operacji. Pomaga to unikać niebezpiecznych rzutowań i utrzymywać bezpieczeństwo typów.

Przykłady zastosowania:

  • Praca z kolekcjami, gdy ważny jest tylko fakt istnienia elementów, a nie ich konkretny typ.
  • Rzutowania typów dla obiektów generycznych.
  • Interoperacyjność z kodem Java używającym typów raw.