W Kotlinie generyki (parametry generyczne) są domyślnie usuwane (type erasure): w czasie wykonywania nie ma informacji o typach. To utrudnia refleksję, konwersję typów i odczyt adnotacji typu. Dla większości zadań jest to do przyjęcia — zwykłe generyki działają podobnie jak w Javie.
Funkcje inline z parametrem reified pozwalają "wymusić" na kompilatorze "podstawienie" konkretnego typu w miejscu wywołania, dzięki czemu funkcja może wykonywać operacje z typem na etapie wykonywania (np. przeprowadzać kontrole, tworzyć nowe instancje za pomocą refleksji itp.). Jednak reified może być stosowane tylko do parametrów w funkcjach inline.
Przykład porównania:
// Zwykły generyk fun <T> printType(t: T) { println(t.javaClass) // Wywoła ClassCastException dla List<Int> i innych. } // z reified inline fun <reified T> printType(t: T) { println(T::class.simpleName) } fun main() { printType(123) // Wyświetli: Int printType("hello") // Wyświetli: String }
Praktyka zastosowania: Najczęściej używane do sprawdzania typu, rzutowania, refleksji, tworzenia instancji, gdzie w inny sposób nie można uzyskać typu.
"Czy funkcja z typem reified może być nie inline?"
reified działa tylko w funkcjach inline. W przeciwnym razie podstawienie typu na etapie kompilacji jest niemożliwe.Przykład błędnego użycia:
fun <reified T> failFunction() {} // Błąd kompilacji: parametr typu reified może być używany tylko w funkcji inline
Poprawnie:
inline fun <reified T> goodFunction() {}
Historia
W projekcie zaistniała potrzeba uniwersalnego parsowania ciągów JSON w dowolny typ przez funkcję z parametrem generycznym. Standardowa realizacja przez
fun <T> parse(json: String): Tnie działała poprawnie z powodu type erasure — nie można było uzyskać Class<T> do parsowania kolekcji i ogólnych modeli. Rozwiązano to przez inline z typem reified — problem zniknął.
Historia
Jeden z programistów próbował tworzyć instancje typu T za pomocą zwykłego konstruktora
T(), nie używając inline i reified. Na etapie kompilacji wystąpił błąd, ponieważ informacja o typie została usunięta. Przepisywanie na inline fun <reified T: Any> udało się rozwiązać wszystko standardowymi środkami języka.
Historia
Przy próbie użycia reified w zwykłej funkcji (bez inline) — IDE wydało mylącą informację o błędzie kompilacji. Programista długo szukał przyczyny, dopóki nie zapoznał się z dokumentacją i nie poprawił funkcji, dodając inline.