Smart casting — это механизм, при котором компилятор Kotlin автоматически "понижает" тип после проверки на определённый тип или null. Это позволяет использовать свойства и методы того типа, в который произведён каст, без явного преобразования.
fun demo(x: Any) { if (x is String) { println(x.length) // x автоматически приведён к String } }
Работает с:
is / !is операторами (например, в if или when)if (x != null))when-выражениямиНе работает:
val str: String? = getString() if (str != null) println(str.length) // smart cast
val something: Any get() = fetch() if (something is String) { println(something.length) // Error: smart cast невозможен }
Можно ли рассчитывать на smart cast для open или var свойств класса внутри методов?
Нет! Smart cast работает только с локальными переменными и val-свойствами в final-классах. Для открытых (open) или var-свойств, компилятор не уверен, может ли значение измениться другими потоками или потомками. Для них требуется ручной cast или локальная переменная.
open class Base { open var maybeString: Any? = "abc" fun check() { if (maybeString is String) { // println(maybeString.length) // Error: Smart cast невозможен val asString = maybeString as String println(asString.length) // Явный cast } } }
История
В одном проекте для логики экранов использовали open var свойства model данных. Программист полагался на smart-cast после проверки if (model is SomeType), однако при компиляции пришлось все вручную приводить типы, что ухудшило читаемость и добавило код дублирования из-за незнания ограничения smart cast на var/open.
История
При получении данных через геттер (например, через делегат или валидацию), smart cast для значения не сработал. Разработчик не понял причин и несколько часов тратил на отладку, пока не выяснил, что компилятор не применяет smart cast к таким геттерам, т.к. они могут возвращать разное значение между вызовами.
История
В проекте при обработке nullable-значений через if (obj != null) smart cast работал внутри ветки, а при распараллеливании кода появлялись NullPointerException из-за обращений вне области гарантии. Это показало недостаточное понимание локального действия smart cast и особенностей многопоточных сценариев работы с nullable-переменными.