In Kotlin i generici (parametri generici) per impostazione predefinita sono soggetti a "type erasure": durante l'esecuzione non ci sono informazioni sui tipi. Questo complica la riflessione, la conversione dei tipi e la lettura delle annotazioni per tipo. Per la maggior parte dei compiti, questo è accettabile: i generici normali funzionano in modo simile a Java.
Le funzioni inline con il parametro reified consentono di "forzare" il compilatore a "sostituire" un tipo specifico nel punto di chiamata, permettendo alla funzione di eseguire operazioni con il tipo a tempo di esecuzione (ad esempio, effettuare controlli, creare nuove istanze tramite riflessione, ecc.). Tuttavia, reified può essere applicato solo a parametri in funzioni inline.
Esempio di confronto:
// Generic normale fun <T> printType(t: T) { println(t.javaClass) // Genererà ClassCastException per List<Int> e altro. } // con reified inline fun <reified T> printType(t: T) { println(T::class.simpleName) } fun main() { printType(123) // Stampa: Int printType("hello") // Stampa: String }
Pratica di applicazione: Viene utilizzato principalmente per controllare il tipo, il casting, la riflessione, la creazione di istanze, dove non è possibile ottenere il tipo in altro modo.
"Può una funzione con tipo reified non essere inline?"
reified funziona solo nelle funzioni inline. Altrimenti, non è possibile sostituire il tipo durante la compilazione.Esempio di utilizzo errato:
fun <reified T> failFunction() {} // Errore di compilazione: il parametro di tipo reified può essere utilizzato solo su una funzione inline
Corretto:
inline fun <reified T> goodFunction() {}
Storia
In un progetto era necessario analizzare universalmente le stringhe JSON in qualsiasi tipo tramite una funzione con un parametro generico. L'implementazione standard tramite
fun <T> parse(json: String): Tnon funzionava correttamente a causa della type erasure — non era possibile ottenere Class<T> per analizzare collezioni e modelli generici. Abbiamo risolto tramite inline con tipo reified — il problema è scomparso.
Storia
Uno degli sviluppatori cercava di creare istanze del tipo T utilizzando un costruttore normale
T(), senza usare inline e reified. Durante la compilazione si è verificato un errore, poiché le informazioni sul tipo erano state cancellate. Riscrivendo in inline fun <reified T: Any> siamo riusciti a risolvere tutto con i mezzi standard del linguaggio.
Storia
Tentando di utilizzare reified in una normale funzione (senza inline) — l'IDE ha restituito un errore di compilazione fuorviante. Lo sviluppatore ha cercato a lungo la causa, fino a quando non ha studiato la documentazione e ha corretto la funzione, aggiungendo inline.