Контекстные параметры
Контекстные параметры позволяют функциям и свойствам объявлять зависимости, неявно доступные в окружающем контексте.
Контекстные параметры избавляют от необходимости вручную передавать значения, например сервисы или зависимости, которые используются совместно и редко меняются в рамках набора вызовов функций.
Чтобы объявить контекстные параметры для свойств и функций, используйте ключевое слово context, за которым следует список параметров, каждый из которых объявляется как name: Type. Вот пример с зависимостью от интерфейса UserService:
// UserService defines the dependency required in context
interface UserService {
fun log(message: String)
fun findUserById(id: Int): String
}
// Declares a function with a context parameter
context(users: UserService)
fun outputMessage(message: String) {
// Uses log from the context
users.log("Log: $message")
}
// Declares a property with a context parameter
context(users: UserService)
val firstUser: String
// Uses findUserById from the context
get() = users.findUserById(1)
fun main() {
val users = object : UserService {
override fun log(message: String) {
println(message)
}
override fun findUserById(id: Int): String {
return "User $id"
}
}
context(users) {
outputMessage("Looking up the first user")
println(firstUser)
// User 1
}
}
Если вам не нужно обращаться к параметру напрямую, в качестве имени контекстного параметра можно использовать _. Анонимный контекстный параметр по-прежнему может удовлетворять требованиям вызываемых функций к контекстным параметрам, но обратиться к нему по имени нельзя. Чтобы явно получить доступ к его значению, используйте contextOf<T>():
// Uses "_" as context parameter name
context(_: UserService)
fun logWelcome() {
// The anonymous parameter satisfies the UserService context parameter
// required by outputMessage()
outputMessage("Welcome!")
// Retrieves the UserService value explicitly
contextOf<UserService>().log("Hi!")
}
Разрешение контекстных параметров
Kotlin разрешает контекстные параметры в месте вызова, выполняя поиск соответствующих значений контекста в текущей области видимости. Kotlin сопоставляет их по типу. Если на одном уровне области видимости есть несколько подходящих значений, компилятор сообщает о неоднозначности:
// UserService defines the dependency required in context
interface UserService {
fun log(message: String)
}
// Declares a function with a context parameter
context(users: UserService)
fun outputMessage(message: String) {
users.log("Log: $message")
}
fun main() {
// Implements UserService
val serviceA = object : UserService {
override fun log(message: String) = println("A: $message")
}
// Implements UserService
val serviceB = object : UserService {
override fun log(message: String) = println("B: $message")
}
// Both serviceA and serviceB match the expected UserService type at the call site
context(serviceA, serviceB) {
// This results in an ambiguity error
outputMessage("This will not compile")
}
}
Явная передача аргументов контекста
Если перегруженные функции различаются только контекстными параметрами, вызов может стать неоднозначным, когда доступны несколько подходящих значений контекста.
Чтобы устранить неоднозначность, передайте явный аргумент контекста в месте вызова:
class EmailSender
class SmsSender
context(emailSender: EmailSender)
fun sendNotification() {
println("Sent email notification")
}
context(smsSender: SmsSender)
fun sendNotification() {
println("Sent SMS notification")
}
context(defaultEmailSender: EmailSender, defaultSmsSender: SmsSender)
fun notifyUser() {
// Selects the overload with the EmailSender context parameter
sendNotification(emailSender = defaultEmailSender)
// Selects the overload with the SmsSender context parameter
sendNotification(smsSender = defaultSmsSender)
}
Явные аргументы контекста также можно использовать, чтобы уменьшить вложенность некоторых вызовов функций:
Для отдельного вызова используйте явные аргументы контекста, чтобы вызов было проще читать.
Если в нескольких вызовах используются одни и те же аргументы контекста, используйте функцию
context().
Эта функция имеет статус экспериментальной. Чтобы включить её, добавьте следующий параметр компилятора в файл сборки:
kotlin {
compilerOptions {
freeCompilerArgs.add("-Xexplicit-context-arguments")
}
}
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<configuration>
<args>
<arg>-Xexplicit-context-arguments</arg>
</args>
</configuration>
</plugin>
</plugins>
</build>
Ограничения
Работа над контекстными параметрами продолжается. К текущим ограничениям относятся:
Конструкторы не могут объявлять контекстные параметры.
У свойств с контекстными параметрами не может быть резервных полей или инициализаторов.
Свойства с контекстными параметрами не могут использовать делегирование.
Несмотря на эти ограничения, контекстные параметры упрощают управление зависимостями благодаря упрощённому внедрению зависимостей, улучшенному проектированию DSL и операциям с ограниченной областью видимости.
© 2010–2026 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/context-parameters.html