Spec-Zone.ru › Kotlin 1.8

Требования к опциональному использованию

Стандартная библиотека 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, вы можете добавить аргументы следующим образом:

tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask<*>>().configureEach {
    compilerOptions.freeCompilerArgs.add("-opt-in=org.mylibrary.OptInAnnotation")
}
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask).configureEach {
    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 и укажите объяснение в сообщении о deprecation.

@Deprecated("This opt-in requirement is not used anymore. Remove its usages from your code.")
@RequiresOptIn
annotation class ExperimentalDateTime
Последнее изменение: 10 января 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