Введение в контекстные параметры в Kotlin
Иногда операцию удобнее описать так, будто рядом уже лежит готовый сервис - журнал, хранилище или счетчик. Передавать его каждый раз отдельным аргументом получается шумно, а глобальная переменная ломает структуру программы.
Контекстный параметр объявляют перед
сигнатурой функции: ключевое слово context,
в скобках имя и тип объекта, затем обычное
fun с остальными аргументами. Внутри тела
имя из context доступно как переменная.
Снаружи объект подставляют блоком context
со значением и лямбдой. Пока выполняется лямбда,
все функции с таким контекстом «видят» переданный
экземпляр.
Класс Logger пишет строку в консоль, а
функция greet берет имя и передает его
в журнал через контекст, без параметра типа
Logger в списке аргументов:
class Logger {
fun write(text: String) {
println(text)
}
}
context(logger: Logger)
fun greet(name: String) {
logger.write(name)
}
Точка входа создает журнал и открывает область, где контекст уже задан. Вызов внутри блока собирается компилятором:
fun main() {
val logger = Logger()
context(logger) {
greet("ann")
}
}
Такой прием не добавляет полей в класс и не меняет его публичный API. Контекст живет только на время блока и явно указан в месте вызова.
Запись context(имя: Тип) перед функцией -
стабильная часть Kotlin 2.4. Объект
остается обычным экземпляром класса, а связь
с функцией задается явно в месте вызова блока
context.