Spec-Zone.ru › Kotlin 2

Контекстные параметры

Контекстные параметры заменяют устаревшую экспериментальную функцию под названием получатели контекста. Основные различия между ними описаны в документе по проектированию контекстных параметров. Для перехода с получателей контекста на контекстные параметры можно воспользоваться поддержкой миграции в IntelliJ IDEA, описанной в соответствующей публикации в блоге.

Контекстные параметры позволяют функциям и свойствам объявлять зависимости, неявно доступные в окружающем контексте.

Контекстные параметры избавляют от необходимости вручную передавать значения, например сервисы или зависимости, которые используются совместно и редко меняются в рамках набора вызовов функций.

Чтобы объявить контекстные параметры для свойств и функций, используйте ключевое слово 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 и операциям с ограниченной областью видимости.

29 июля 2026
Использование построителей с выводом типов построителяВстраиваемые функции

© 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API