Spec-Zone.ru › Kotlin 1.4

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

Аннотации требований к включению @RequiresOptIn и @OptIn являются экспериментальными. Подробности использования см. ниже.

Аннотации @RequireOptIn и @OptIn были введены в версии 1.3.70 для замены ранее использовавшихся @Experimental и @UseExperimental; в то же время, опция компилятора -Xopt-in заменила -Xuse-experimental.

Стандартная библиотека Kotlin предоставляет механизм для требования и предоставления явного согласия на использование определенных элементов 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
}

Как видно из этого примера, помеченная функция является частью API @MyDateTime. Таким образом, такое включение распространяет требование к включению на код клиента; клиенты увидят то же сообщение об ошибке и также должны будут дать согласие. Для использования нескольких 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, используемых в её теле.

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

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

Включение на уровне модуля

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

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

compileKotlin {
    kotlinOptions {
        freeCompilerArgs += "-Xopt-in=org.mylibrary.OptInAnnotation"
    }
}
tasks.withType<KotlinCompile>().all {
    kotlinOptions.freeCompilerArgs += "-Xopt-in=org.mylibrary.OptInAnnotation"
}

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

sourceSets {
    all {
        languageSettings {
            useExperimentalAnnotation('org.mylibrary.OptInAnnotation')
        }
    }
}
sourceSets {
    all {
        languageSettings.useExperimentalAnnotation("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>-Xopt-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 сохранение
  • Не должно быть EXPRESSION и FILE среди целей
  • Параметров быть не должно.

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

  • 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 {}

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

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

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

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

@Deprecated("This opt-in requirement is not used anymore. Remove its usages from your code.")
@RequiresOptIn
annotation class ExperimentalDateTime

Экспериментальный статус требований к включению

Механизм требований к включению является экспериментальным в Kotlin 1.3. Это означает, что в будущих версиях он может быть изменён таким образом, чтобы стать несовместимым.

Чтобы пользователи аннотаций @OptIn и @RequiresOptIn были осведомлены об их экспериментальном статусе, компилятор генерирует предупреждения при компиляции кода с этими аннотациями:

This class can only be used with the compiler argument '-Xopt-in=kotlin.RequiresOptIn'

Чтобы удалить предупреждения, добавьте аргумент компилятора -Xopt-in=kotlin.RequiresOptIn.

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

Spec-Zone.ru

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