Extension functions
Учимся добавлять методы к чужим типам, не меняя их код.
Extension function (функция-расширение) — функция, которая добавляет новый метод к уже существующему типу, не изменяя его исходный код и не наследуясь от него.
Иногда хочется добавить удобный метод к String или List, но менять их исходники нельзя. Kotlin решает это через функции-расширения — одну из самых любимых возможностей языка.
Объявление расширения
Перед именем функции указывают тип-получатель и точку. Внутри функции this ссылается на объект, у которого её вызвали.
fun String.shout(): String {
return this.uppercase() + "!"
}
fun main() {
println("привет".shout())
println("kotlin".shout())
}Вывод:
ПРИВЕТ! KOTLIN!
Расширения для своих типов
Расширять можно любой тип, в том числе коллекции. Это позволяет писать выразительные «методы», как будто они встроены в тип.
fun List<Int>.secondOrNull(): Int? {
return if (this.size >= 2) this[1] else null
}
fun main() {
println(listOf(10, 20, 30).secondOrNull())
println(listOf(5).secondOrNull())
}Вывод:
20 null
Расширения-свойства
Аналогично методам можно добавлять и свойства-расширения — например, удобное вычисляемое свойство.
val String.firstWord: String
get() = this.split(" ").first()
fun main() {
println("Котлин очень крут".firstWord)
}Вывод:
Котлин
Как работает под капотом
Расширения — это «синтаксический сахар»: на самом деле объект не меняется. Компилятор превращает вызов "привет".shout() в обычную статическую функцию, которой объект "привет" передаётся первым аргументом. Поэтому расширение не имеет доступа к приватным полям типа и не может его по-настоящему изменить — оно лишь добавляет удобный синтаксис вызова. Расширения разрешаются статически, по объявленному типу переменной.
Частые ошибки
- Ждать доступа к приватным полям типа. Расширение видит только публичный интерфейс.
- Думать, что расширение «встраивается» в класс. Это статическая функция; сам класс не меняется.
- Создавать расширение там, где хватает обычной функции. Расширение оправдано, когда читается естественнее как метод объекта.
Итог
- Функция-расширение добавляет метод к существующему типу без его изменения.
- Внутри расширения
this— это объект-получатель. - Расширять можно и свои, и чужие типы, включая коллекции.
- Под капотом это статическая функция без доступа к приватным членам.