Что такое reified в inline функциях Kotlin и зачем он нужен
Что проверяют
Понимаете ли вы, что такое стирание типов, и почему обход требует именно встраивания.
Как отвечать
На JVM обобщения стираются: во время выполнения List<String> и List<Int> это один и тот же тип. Поэтому в обычной обобщённой функции нельзя написать T::class, is T или as T без предупреждения: информации о типе там уже нет.
reified снимает это ограничение, но работает только вместе с inline. Причина прямая: компилятор встраивает тело функции в место вызова и подставляет туда конкретный тип вместо параметра. То есть типа во время выполнения по-прежнему нет, просто нужный код собран заранее для каждой точки вызова.
Классические применения:
inline fun <reified T> Gson.fromJson(json: String): T =
fromJson(json, T::class.java)
inline fun <reified T : Activity> Context.start() =
startActivity(Intent(this, T::class.java))Вместо startActivity(Intent(this, ProfileActivity::class.java)) пишется start<ProfileActivity>(). В стандартной библиотеке на этом же построен filterIsInstance<T>().
Ограничения, которые стоит назвать:
- без
inlineне работает, это не отдельный модификатор; - из Java такую функцию вызвать нельзя: там нет ни встраивания, ни овеществлённых типов;
- нельзя создать экземпляр
Tпросто так, конструктор всё равно неизвестен: нужен либоT::class.java.newInstance()через рефлексию, либо переданная фабрика; - встраивание раздувает код: тело копируется в каждую точку вызова, поэтому большие функции так помечать не стоит;
- публичная встраиваемая функция не видит приватные члены своего класса, потому что её тело окажется в чужом коде.
Где спотыкаются
Пытаются использовать reified без inline.
Считают, что тип действительно доступен во время выполнения.
Помечают inline большие функции ради стиля и раздувают сборку.
Не могут объяснить, почему такую функцию не вызвать из Java.