Spec-Zone.ru › Kotlin 1.9

Требования к включению

Стандартная библиотека Kotlin предоставляет механизм для требования и предоставления явного согласия на использование определенных элементов API. Этот механизм позволяет разработчикам библиотек информировать пользователей о своих API о конкретных условиях, требующих включения, например, если API находится в экспериментальном состоянии и, вероятно, изменится в будущем.

Чтобы предотвратить возможные проблемы, компилятор предупреждает пользователей о таких API об этих условиях и требует их включения перед использованием API.

Включение использования API

Если автор библиотеки помечает объявление из API библиотеки как требующее включения, вы должны дать явное согласие на его использование в вашем коде. Существует несколько способов включения таких API, все они применимы без технических ограничений. Вы вольны выбрать способ, который вам больше подходит.

Распространение включения

Когда вы используете API в коде, предназначенном для использования третьими лицами (библиотека), вы можете распространить его требование к включению на ваш API. Для этого добавьте в свое объявление аннотацию требования к включению используемого API в его теле. Это позволит вам использовать элементы API, требующие включения.

// Library code
@RequiresOptIn(message = "This API is experimental. It may be changed in the future without notice.")
@Retention(AnnotationRetention.BINARY)
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
annotation class MyDateTime // Opt-in requirement annotation

@MyDateTime                            
class DateProvider // A class requiring opt-in
// Client code
fun getYear(): Int {  
    val dateProvider: DateProvider // Error: DateProvider requires opt-in
    // ...
}

@MyDateTime
fun getDate(): Date {  
    val dateProvider: DateProvider // OK: the function requires opt-in as well
    // ...
}

fun displayDate() {
    println(getDate()) // Error: getDate() requires opt-in
}

Как видно из этого примера, аннотированная функция, кажется, является частью @MyDateTime API. Таким образом, такое включение распространяет требование к включению на код клиента; его клиенты увидят то же сообщение об ошибке и также будут обязаны согласиться.

Неявные использования API, требующих включения, также требуют включения. Если элемент API не имеет аннотации требования к включению, но его сигнатура включает тип, объявленный как требующий включения, его использование все равно вызовет предупреждение. См. пример ниже.

// Client code
fun getDate(dateProvider: DateProvider): Date { // Error: DateProvider requires opt-in
    // ...
}

fun displayDate() {
    println(getDate()) // Warning: the signature of getDate() contains DateProvider, which requires opt-in
}

Для использования нескольких API, требующих включения, пометьте объявление всеми их аннотациями требования к включению.

Нераспространяемое включение

В модулях, которые не экспонируют собственный API, такие как приложения, вы можете включить использование API без распространения требования к включению на ваш код. В этом случае пометьте объявление @OptIn, передавая аннотацию требования к включению в качестве аргумента:

// Library code
@RequiresOptIn(message = "This API is experimental. It may be changed in the future without notice.")
@Retention(AnnotationRetention.BINARY)
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
annotation class MyDateTime // Opt-in requirement annotation

@MyDateTime                            
class DateProvider // A class requiring opt-in
// Client code
@OptIn(MyDateTime::class)
fun getDate(): Date { // Uses DateProvider; doesn't propagate the opt-in requirement
    val dateProvider: DateProvider
    // ...
}

fun displayDate() {
    println(getDate()) // OK: opt-in is not required
}

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

Обратите внимание, что если @OptIn применяется к объявлению, сигнатура которого содержит тип, объявленный как требующий включения, включение все равно будет распространено:

// Client code
@OptIn(MyDateTime::class)
fun getDate(dateProvider: DateProvider): Date { // Has DateProvider as a part of a signature; propagates the opt-in requirement
    // ...
}

fun displayDate() {
    println(getDate()) // Warning: getDate() requires opt-in
}

Чтобы использовать API, требующее включения, во всех функциях и классах в файле, добавьте аннотацию на уровне файла @file:OptIn в начало файла, перед указанием пакета и импортами.

// Client code
@file:OptIn(MyDateTime::class)

Модульное включение

Опция компилятора -opt-in доступна начиная с Kotlin 1.6.0. Для более ранних версий Kotlin используйте -Xopt-in.

Если вы не хотите аннотировать каждое использование API, требующего включения, вы можете включить их для всего модуля. Для включения использования API в модуле скомпилируйте его с аргументом -opt-in, указав полное квалифицированное имя аннотации требования к включению используемого API: -opt-in=org.mylibrary.OptInAnnotation. Компиляция с этим аргументом эквивалентна добавлению аннотации @OptIn(OptInAnnotation::class) к каждому объявлению в модуле.

Если вы строит свой модуль с помощью Gradle, вы можете добавить аргументы так:

import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask
// ...

tasks.named<KotlinCompilationTask<*>>("compileKotlin").configure {
    compilerOptions.freeCompilerArgs.add("-opt-in=org.mylibrary.OptInAnnotation")
}

import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask
// ...

tasks.named('compileKotlin', KotlinCompilationTask) {
    compilerOptions {
        freeCompilerArgs.add("-opt-in=org.mylibrary.OptInAnnotation")
    }
}

Если ваш модуль Gradle является многоплатформенным модулем, используйте метод optIn:

sourceSets {
    all {
        languageSettings.optIn("org.mylibrary.OptInAnnotation")
    }
}
sourceSets {
    all {
        languageSettings {
            optIn('org.mylibrary.OptInAnnotation')
        }
    }
}

Для Maven это будет:

<build>
    <plugins>
        <plugin>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-maven-plugin</artifactId>
            <version>${kotlin.version}</version>
            <executions>...</executions>
            <configuration>
                <args>
                    <arg>-opt-in=org.mylibrary.OptInAnnotation</arg>                    
                </args>
            </configuration>
        </plugin>
    </plugins>
</build>

Для включения нескольких API на уровне модуля добавьте один из описанных аргументов для каждого маркера требования к включению, используемого в вашем модуле.

Требовать включение для API

Создать аннотации требования к включению

Если вы хотите потребовать явного согласия на использование API вашего модуля, создайте класс аннотаций, который будет использоваться в качестве аннотации требования к включению. Этот класс должен быть аннотирован с помощью @RequiresOptIn:

@RequiresOptIn
@Retention(AnnotationRetention.BINARY)
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
annotation class MyDateTime

Аннотации требования к включению должны удовлетворять нескольким требованиям:

  • BINARY или RUNTIME сохранение

  • Без EXPRESSION, FILE, TYPE, или TYPE_PARAMETER среди целей

  • Без параметров.

Требование включения может иметь один из двух уровней серьезности уровней:

  • RequiresOptIn.Level.ERROR. Включение обязательно. В противном случае код, использующий помеченный API, не будет компилироваться. Уровень по умолчанию.

  • RequiresOptIn.Level.WARNING. Включение не обязательно, но желательно. Без него компилятор выдает предупреждение.

Для установки нужного уровня укажите параметр level аннотации @RequiresOptIn.

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

@RequiresOptIn(level = RequiresOptIn.Level.WARNING, message = "This API is experimental. It can be incompatibly changed in the future.")
@Retention(AnnotationRetention.BINARY)
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
annotation class ExperimentalDateTime

Если вы публикуете несколько независимых функций, требующих включения, объявляйте аннотацию для каждой. Это делает использование API безопаснее для ваших клиентов: они могут использовать только те функции, которые они явно принимают. Это также позволяет вам независимо отключать требования к включению для функций.

Помечать элементы API

Для того, чтобы потребовать включение для использования элемента API, аннотируйте его объявление аннотацией требования к включению:

@MyDateTime
class DateProvider

@MyDateTime
fun getTime(): Time {}

Обратите внимание, что для некоторых языковых элементов аннотация требования к включению неприменима:

  • Вы не можете аннотировать вспомогательное поле или getter свойства, только само свойство.

  • Вы не можете аннотировать локальную переменную или параметр значения.

Требования к включению для предварительно стабильных API

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

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

Чтобы позволить пользователям API обновить свои модули соответственно (удалить аннотации из своего кода и перекомпилировать), пометьте аннотации как @Deprecated и предоставьте объяснение в сообщении о устаревании.

@Deprecated("This opt-in requirement is not used anymore. Remove its usages from your code.")
@RequiresOptIn
annotation class ExperimentalDateTime
Последнее изменение: 06 июня 2023
Операции с картами Функции области

© 2010–2023 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/opt-in-requirements.html

Spec-Zone.ru

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