Ce face reified
Pe JVM, tipurile generice se șterg la compilare (type erasure): într-o funcție obișnuită fun <T> f() nu poți afla la rulare ce este T, deci x is T nu compilează. Dacă funcția este inline și parametrul de tip este marcat reified, compilatorul copiază funcția la fiecare apel și pune acolo tipul real. Atunci is T, as T și T::class funcționează.
Biblioteca standard folosește reified în filterIsInstance<T>(), emptyArray<T>() sau typeOf<T>(). O funcție reified poate fi apelată doar cu tipuri cunoscute la compilare, nu cu un alt T ne-reified.
Exemple
Exemplul 1: Filtrare după tip
doar<String>() verifică fiecare element cu is T; fără reified verificarea nu ar fi posibilă.
inline fun <reified T> List<Any>.doar(): List<T> {
val rezultat = mutableListOf<T>()
for (x in this) if (x is T) rezultat.add(x)
return rezultat
}
fun main() {
val amestec: List<Any> = listOf("Ana", 10, "Iași", 3.5, 7, true)
println(amestec.doar<String>())
println(amestec.doar<Int>())
println(amestec.doar<Boolean>())
}
Rezultat
[Ana, Iași]
[10, 7]
[true]
Exemplul 2: Numele tipului cu T::class
T::class.simpleName dă numele clasei reale de la fiecare apel. Pentru List<Int> se vede doar List: tipul elementelor se șterge.
class Produs
class Comanda
inline fun <reified T> descrie(): String = "Lucrez cu tipul ${T::class.simpleName}"
fun main() {
println(descrie<Produs>())
println(descrie<Comanda>())
println(descrie<String>())
println(descrie<List<Int>>())
}
Rezultat
Lucrez cu tipul Produs
Lucrez cu tipul Comanda
Lucrez cu tipul String
Lucrez cu tipul List
Exemplul 3: Conversie sigură cu as? T
valoare<T> citește o setare din map și o returnează doar dacă are tipul cerut; altfel dă valoarea implicită.
val setari: Map<String, Any> = mapOf("oras" to "Cluj", "port" to 8080, "debug" to false)
inline fun <reified T> valoare(cheie: String, implicit: T): T = setari[cheie] as? T ?: implicit
fun main() {
val oras = valoare("oras", "necunoscut")
val port = valoare("port", 80)
val gresit = valoare("oras", 0)
println("Oraș: $oras, port: $port, oraș ca număr: $gresit")
}
Rezultat
Oraș: Cluj, port: 8080, oraș ca număr: 0
Greșeli frecvente
reifiedîntr-o funcție care nu esteinline: eroareonly type parameters of inline functions can be reified.- Verificarea tipului complet al unei colecții:
x is List<String>verifică doar că este o listă; tipul elementelor se șterge și acolo.T::classpentruList<Int>dăList. - Apelarea din altă funcție generică fără
reified:fun <T> g() = doar<T>()nu compilează, pentru căTnu mai este cunoscut.
Comenzi înrudite
inline, noinline și crossinline: inline copiază corpul funcției și lambda-urile ei în locul apelului; noinline și crossinline controlează lambda-urile primite.Generics (<T>) și where: Generics permit clase și funcții care lucrează cu orice tip (T), verificat la compilare; where adaugă mai multe restricții pe T.is, !is și smart cast: is verifică tipul unei valori; după verificare, compilatorul o tratează automat ca acel tip (smart cast).as și as? (conversie de tip): as tratează o valoare ca alt tip (aruncă excepție dacă nu se potrivește); as? întoarce null în loc de excepție.Iterable.filterIsInstance: Păstrează doar elementele de un anumit tip și întoarce o listă cu acel tip.