Что такое reified в Kotlin

Ответ

reified — это модификатор типа, который позволяет получить доступ к информации о типе во время выполнения в обобщённых функциях. Обычно в JVM стирается информация о generic-типах, но reified сохраняет её.

Используется только с inline-функциями, так как компилятор подставляет реальный тип на этапе компиляции.

Пример:

inline fun <reified T> checkType(value: Any) {
    if (value is T) {
        println("Value is of type ${T::class.simpleName}")
    }
}

// Использование
checkType<String>("Hello") // Выведет: Value is of type String

Без reified пришлось бы передавать Class<T> параметром. Особенно полезно в случаях, когда нужно работать с классами напрямую, например, в Gson.fromJson() или при создании интентов.

Ответ 18+ 🔞

А, ну это про reified! Слушай, это вообще одна из самых хитрожопых штук в Котлине, если честно. Представь себе: ты пишешь дженерик-функцию, а потом пытаешься внутри проверить value is T — и тут тебе компилятор такой: "Не-а, братан, нихуя не выйдет, я уже всё стёр". Это называется type erasure, такая особенность JVM, ёпта. Всю информацию о generic-типах на этапе выполнения просто выкидывают, будто её и не было. И ты остаёшься с носом, с желанием проверить тип, но без возможности это сделать.

И вот тут на сцену выходит наш спаситель — reified. Это такой модификатор, который говорит компилятору: "Эй, дружище, не стирай этот тип, а? Оставь его, мне ещё нужно". Но есть одна важная деталь, блядь: работает это волшебство только с inline-функциями. Потому что когда функция inline, компилятор не просто вызывает её, а тупо вставляет её код прямо на место вызова. И в этот момент он уже знает, какой конкретный тип ты туда передал, и может его подставить. Получается такой маленький, но гордый трюк.

Вот смотри, без reified пришлось бы городить огород:

fun <T> checkType(value: Any, clazz: Class<T>) {
    if (clazz.isInstance(value)) {
        println("Value is of type ${clazz.simpleName}")
    }
}
// Вызывать так: checkType("Hello", String::class.java)

Совсем не сахар, да? Вечно таскать с собой этот Class<T> — терпения ноль, ебать.

А с reified всё становится красиво и понятно, как божий день:

inline fun <reified T> checkType(value: Any) {
    if (value is T) {
        println("Value is of type ${T::class.simpleName}")
    }
}
// А используешь просто: checkType<String>("Hello")

Красота, правда? И проверка типа is T работает, и имя класса через T::class можно получить. Удобство — овердохуища.

Где это чаще всего применяют? Да везде, где нужно работать с классами напрямую. Самые жирные кейсы:

  1. Парсинг JSON. Вместо Gson().fromJson(json, MyDataClass::class.java) можно написать свою обёртку: inline fun <reified T> fromJson(json: String): T. И внутри уже использовать T::class.java. Чистая магия.
  2. Навигация в Android. Создание интентов или передача аргументов между фрагментами. Чтобы не писать MyFragment::class.java.name, можно сделать функцию inline fun <reified T : Fragment> newInstance() = T::class.java.newInstance().
  3. Всякие фабрики и создание объектов по типу. Когда нужно, чтобы функция возвращала экземпляр именно того класса, который ты указал в generics.

Короче, reified — это как секретное оружие. Кажется мелочью, а нахуй так упрощает жизнь, когда понимаешь, как и где его применить. Главное помни связку: reified работает только внутри inline-функции. Без этого — нихуя не получится.