В Kotlin модификатор const val используется только для compile-time констант в top-level (на уровне файла), либо внутри объектов (object) и компаньон-объектов. Свойства, объявленные как val внутри классов, становятся обычными final property без статической инициализации. Важная особенность: const val наследоваться не может, а val можно переопределять (если разрешено).
Константы (const val) не могут быть абстрактными, так как должны иметь значение на этапе компиляции. Обычные val позволяют реализовать паттерн констант в иерархиях через открытые свойства, однако в рантайме они будут доступны через геттер, что отличается от компиляции в Java.
open class Base { open val info: String = "base" } class Child : Base() { override val info = "child" } object Constants { const val APPLICATION_NAME = "MyApp" }
Можно ли объявить
const valв интерфейсе или абстрактном классе и затем переопределить/наследовать его?
Нет. В Kotlin нельзя объявить const val внутри интерфейса или абстрактного класса — это допускается только на уровне объекта (object) и top-level. Аналогичных static final переменных, доступных для наследования, нет.
interface Foo { // const val X = "constant" // compile error: const 'val' are only allowed on top-level, in objects, or in companion objects }
История
Команда пыталась переиспользовать строковые константы через наследование интерфейса в нескольких модулях Android, объявив их как
const val— получили ошибку компиляции и были вынуждены переместить константы на top-level, что ухудшило капсуляцию.
История
В проекте перевели все Java static final поля в Kotlin
val-поля в открытых классах, ожидая такого же поведения (compile-time const), но они стали обычными property с геттером. В результате увеличилось время доступа, что негативно сказалось на горячих путях (hot path) микросервисного приложения.
История
При портировании Java-классов constants-контейнеров в Kotlin, разработчики сделали constants внутри companion object, но столкнулись с проблемой доступа с Java-кода: константы были видны как поля самого компаньона, а не класса, что вызвало путаницу в API и дополнительные баги интероперабельности.