Требования к включению
Аннотации требований к включению
@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