Урок 21: Extension (функции-расширения) языка Kotlin
Оглавление:
extension-функции в Kotlin
Extension функция – это функция, которая не являясь участником какого-то класса (то есть не находясь внутри определенного класса), расширяет его функционал, имея доступ к публичным полям.
Чтобы лучше понять что это такое, лучше разобраться в вопросе “когда применяется extension функция?”
Когда применяется extension-функция?
Разберем на примере класса File из стандартной библиотеки Java. Создадим экземпляр этого класса, в скобках указываем название будущего файла.
fun main() {
val file = File("textFile.txt")
}
Провалимся в документацию. File – это класс. Конструктор принимает путь к файлу в систему — в нашем случае относительный путь. У него внутри есть поля и методы для работы с файлами. Например, метод createNewFile() — создает файл, если его не существует.
Но предположим, что нам нужен такой метод для записи текста в файл, который еще и отображает в консоль то, что записано в файл. В классе File этого метода нет, а также у вас нет доступа для редактирования этого файла. Он по умолчанию read only. Потому, что этот файл находится внутри JDK.
![Урок 21: Extension (функции-расширения) языка Kotlin 1 экрана 2026 01 17 в 14.42.19 - Android [Kotlin] для начинающих](https://ievetrov.ru/wp-content/uploads/2021/02/Снимок-экрана-2026-01-17-в-14.42.19.png)
Если нажать на “прицел”, увидим его расположение. Вот тут находятся все инструменты, что мы выбирали при создании проекта. И здесь в стандартной библиотеке лежит этот файл класса File в скомпилированном виде. Редактировать его нельзя.
Применение функции-расширения
Нам нужно записать текст в файл и выполнить какие-то дополнительные манипуляции. Поэтому создадим функцию-расширение для класса File, которая будет записывать текст в файл и выводить информацию в консоль. Дословно это будет звучать так: хочу, чтобы у файла (у класса File) был еще вот такой-то функционал. Extension-функция объявляется как и обычная с ключевого слова fun, однако, перед названием проставляется тип того класса для которого мы расширяем функционал. И пишем этот функционал внутри фигурных скобок созданной функции.
fun main() {
val file = File("textFile.txt")
file.writeToFileAndPrint()
}
fun File.writeToFileAndSend() {
val message = "some message for file"
writeText(message)
println("Запись \"$message\" добавлена в файл $name и отправлена на сервер")
}
И, вызвав эту функцию у объекта класса File, к нему применится определенное действие. Причем можно не просто добавлять свой функционал, а можно еще внутри вызывать какие-то функции из класса, к которому применяем функцию-расширения. В данном случае createNewFile() и getName() (здесь она написана в сокращенном формате name, вместо функции геттера) это функции класса File. *writeText*() тоже применяется к объекту файла, но не напрямую. Об этом будет ниже.
Разработчики стандартной библиотеки Kotlin уже встроили функцию writeText() в стандартную библиотеку Kotlin. Провалимся в исходник и увидим такую же сигнатуру, которую мы написали для создания собственной extension функции. В Котлин уже есть собственная функция для записи текста в файл и она является частью языка.
![Урок 21: Extension (функции-расширения) языка Kotlin 2 экрана 2026 01 17 в 14.45.55 - Android [Kotlin] для начинающих](https://ievetrov.ru/wp-content/uploads/2021/02/Снимок-экрана-2026-01-17-в-14.45.55.png)
Как видите, функция НЕ является частью класса File. Она вообще не рядом с классом File. Однако, расширяет его функционал, за счет указания типа перед названием в сигнатуре функции.
То есть если бы мы писали этот функционал без Котлин, нужно было бы самостоятельно реализовывать весь функционал, описанный в этих функциях. Создавать FileOutputStream, записывать массивы байтов и так далее.
Но сейчас, например, чтобы записать текст в файл нам нужно только воспользоваться extension функцией, которую предоставляет API Kotlin. И применить ее к экземпляру класса File. Такие функции в среде разработки подсвечиваются желтым цветом.
extension-свойства
Помимо функций есть также extension-свойства. Расширения на самом деле не добавляют никаких членов к классам и свойство-расширение не может иметь контейнеры field. Еще их называют Backing fields. Для свойств-расширений нельзя использовать инициализаторы. Их поведение может быть определено только явным образом, с указанием геттеров/сеттеров.
Приведем такой пример. Объявим свойство-расширение nameWithoutExtension. Его будем использовать чтобы получить имя файла без расширения.
public val File.nameWithoutExtension: String
get() = name.substringBeforeLast(".")
Теперь, если вызвать это свойство у объекта файла – получим ожидаемую строку с названием файла, у которого “отсечено” расширение. Выведем код в консоль.
val File.nameWithoutExtension: String
get() = name.substringBeforeLast(".")
fun main() {
val file = File("textFile.txt")
println(file.nameWithoutExtension)
}
Вот в чем крутость Kotlin и крутость функций-расширения. Extension функции позволяют расширять функционал классов, к исходному коду которого у вас нет доступа. Но добавлю на будущее. Не стоит злоупотреблять такими функциями. Если внутри проекта есть какой-то класс, который требует расширения – просто добавьте в него требуемый метод. Во избежание ненужного разброса, так как ваш написанный класс будет в одном месте. А extension’ов вы насоздаете в другом, что может размазать логику по проекту.
Взаимодействие с файлами и extension’ами мы используем в рамках создания курсового проекта телеграм-бота на Kotlin. А также участникам практики доступны более продвинутые темы.
Бесплатные Telegram-боты для обучения
Практика с проверкой кода и помощью ИИ-ментора
AndroidSprint AI Mentor
Проверяет Pull Request'ы в GitHub, проводит тестовые собеседования с голосом и таймером, помогает разбираться с кодом 24/7
Попробовать ИИ-ментора →KotlinSprint Bot
22 урока Kotlin, 220 тестов, 120 практических задач с код-ревью
Начать обучение Kotlin →