Extension properties — это расширения для классов, которые позволяют добавить геттеры и сеттеры без возможности добавления состояния (backing field). В Java такой возможности нет, и аналогом служит написание утилитарных методов. Исторически пришлось для добавления функционала использовать статические методы или Wrapper-объекты.
Проблема: в сторонних классах часто не хватает нужных свойств. Хочется расширить класс лаконично и безопасно, не нарушая инкапсуляцию.
Решение: в Kotlin можно объявить extension property, которая выглядит как обычное свойство, но реализована в виде функций. Это позволяет расширить типы, к которым мы не имеем доступ к исходному коду, удобным способом.
Пример кода:
val String.firstChar: Char get() = this[0] println("Kotlin".firstChar) // K
Ключевые особенности:
Можно ли добавить backing field (состояние) в extension property?
Нет, extension property только вычисляет значение на лету и не может хранить состояние.
Могут ли extension properties переопределять свойства в наследуемых классах?
Нет, extension properties (как и функции-расширения) статичны по сути: они не могут быть переопределены или virtual.
Как extension property компилируется, и почему она не синтаксический аналог обычного свойства?
Extension property на самом деле компилируется в статический геттер (и/или сеттер) функции. Они не включены в сущности класса и видны только в контексте файла, где объявлены.
Негативный кейс
Разработчик попытался добавить extension property для хранения состояния "посещённости" в стандартных View Android:
var View.isVisited: Boolean get() = ... set(value) { ... } // Ошибка: нет хранения
Плюсы:
Минусы:
Позитивный кейс
Реализован extension property для String для получения расширенного формата:
val String.asTitle: String get() = this.replaceFirstChar { it.uppercase() }
Плюсы:
Минусы: