Что такое reified

Ответ

Reified позволяет сохранить информацию о типе во время выполнения в дженериках, что обычно стирается из-за type erasure в JVM. Используется с inline функциями.

Пример:

inline fun <reified T> parseJson(json: String): T {
    return Gson().fromJson(json, T::class.java)
}

// Вызов
val user = parseJson<User>("{...}")

Без reified пришлось бы передавать Class<T> явно. Ограничение: работает только с inline-функциями, так как код подставляется в месте вызова с известным типом.

Ответ 18+ 🔞

А, ну это ж про reified, да? Такая штука, которая в Kotlin'е позволяет не терять тип на этапе выполнения, когда работаешь с дженериками. А то ведь JVM, хитрая жопа, по умолчанию всю эту информацию о типах просто стирает, как будто её и не было — type erasure называется. И остаёшься ты с голым кодом и вопросиками вместо типов.

А с reified ты как будто говоришь компилятору: «Слушай, ёпта, этот тип T — он мне ещё пригодится, не стирай его нахуй, оставь как есть». И компилятор такой: «Ладно, уговорил». Но есть один нюанс, Карл! Работает эта магия только с inline-функциями. Потому что когда функция inline, её код не вызывается, а прямо встраивается в место вызова. И в этот самый момент компилятор уже точно знает, какой конкретный тип ты туда подсунул, и может его подставить. Получается такой вот хитрожопый обход системы.

Вот смотри, без этой фичи пришлось бы танцевать с бубном и тащить Class<T> в аргументах, как в старые добрые времена на Java. Пиздец, неудобно же.

// Старый, скучный способ. Как будто на дворе 2002-й год.
fun <T> parseJson(json: String, clazz: Class<T>): T {
    return Gson().fromJson(json, clazz)
}

// Вызов. Овердохуища boilerplate-кода.
val user = parseJson("{...}", User::class.java)

А теперь, внимание, магия:

inline fun <reified T> parseJson(json: String): T {
    return Gson().fromJson(json, T::class.java) // Во! T::class.java просто работает!
}

// Вызов. Красота, одним махом. Никакого лишнего говна.
val user = parseJson<User>("{...}")

Видишь разницу? Во втором случае ты просто указываешь тип в угловых скобках, и всё. Компилятор под капотом разворачивает этот вызов, подставляет реальный класс User и вуаля — ты получаешь свой типизированный объект. Удобно, ёб твою мать, до безобразия.

Но запомни, чувак: раз только с inline, то и все ограничения inline-функций на тебя распространяются. Нельзя сохранить ссылку на такую функцию, передать её как объект высшего порядка — код должен быть встраиваемым. Но для утилитных штук вроде парсинга JSON или фабрик — это просто песня. Сам от себя охуевал, когда первый раз использовал.